r: rounding when head data

2019-07-26 23:03发布

问题:

I am not able to figure out how to get r to correctly show the head of my data. This is an assignment for Swirl, so I have to figure out how to write my code in a way that Swirl will accept as the answer.
Swirl wants the final printout to look exactly like this:

## Pclass   agecat    Sex      N     survivors   perc_survived
## <int>   <fctr>    <chr>   <int>     <int>         <dbl>
##   1    Under 15  female     2         1        50.000000
##   1    Under 15    male     3         3       100.000000
##   1    15 to 50  female    70        68        97.142857
##   1    15 to 50    male    72        32        44.444444
##   1    Over 50   female    13        13       100.000000
##   1    Over 50     male    26         5        19.230769
#

My code:

 library(dplyr)
 titanic_4 <- titanic %>% 
  select(Survived, Pclass, Age, Sex) %>%
  filter(!is.na(Age)) %>%
  mutate(agecat = cut(Age, breaks = c(0, 14.99, 50, 150), 
                      include.lowest = TRUE,
                      labels = c("Under 15", "15 to 50",
                                 "Over 50"))) %>%
  group_by(Pclass,agecat,Sex) %>%
  summarize(N=n(), survivors = sum(Survived))%>%
  mutate(perc_survived = (signif((100*survivors/N), digits=8)))

print(titanic_4)

Gives:

# A tibble: 18 x 6
# Groups:   Pclass, agecat [9]
   Pclass   agecat    Sex     N survivors perc_survived
    <int>   <fctr>  <chr> <int>     <int>         <dbl>
 1      1 Under 15 female     2         1     50.000000
 2      1 Under 15   male     3         3    100.000000
 3      1 15 to 50 female    70        68     97.142857
 4      1 15 to 50   male    72        32     44.444444
 5      1  Over 50 female    13        13    100.000000
 6      1  Over 50   male    26         5     19.230769
 7      2 Under 15 female    10        10    100.000000
 8      2 Under 15   male     9         9    100.000000
 9      2 15 to 50 female    61        56     91.803279
10      2 15 to 50   male    78         5      6.410256
11      2  Over 50 female     3         2     66.666667
12      2  Over 50   male    12         1      8.333333
13      3 Under 15 female    27        13     48.148148
14      3 Under 15   male    27         9     33.333333
15      3 15 to 50 female    74        33     44.594595
16      3 15 to 50   male   217        29     13.364055
17      3  Over 50 female     1         1    100.000000
18      3  Over 50   male     9         0      0.000000

When I head(titanic_4), r rounds the data in the last column (perc_survivied):

# A tibble: 6 x 6
# Groups:   Pclass, agecat [3]
  Pclass   agecat    Sex     N survivors perc_survived
   <int>   <fctr>  <chr> <int>     <int>         <dbl>
1      1 Under 15 female     2         1      50.00000
2      1 Under 15   male     3         3     100.00000
3      1 15 to 50 female    70        68      97.14286
4      1 15 to 50   male    72        32      44.44444
5      1  Over 50 female    13        13     100.00000
6      1  Over 50   male    26         5      19.23077

However, I would like R to give me six decimal places in perc_survived so that it will look like this:

## Pclass   agecat    Sex      N     survivors   perc_survived
## <int>   <fctr>    <chr>   <int>     <int>         <dbl>
##   1    Under 15  female     2         1        50.000000
##   1    Under 15    male     3         3       100.000000
##   1    15 to 50  female    70        68        97.142857
##   1    15 to 50    male    72        32        44.444444
##   1    Over 50   female    13        13       100.000000
##   1    Over 50     male    26         5        19.230769

Can anyone tell me how to tell r to keep 6 decimal place? Thank you so much!

From Comments:
*Maybe print(titanic[1:6,])? – Florian

I tried the method proposed by Florian, but it did not change the rounding results

> titanic_4 <- titanic %>% 
+     select(Survived, Pclass, Age, Sex) %>%
+     filter(!is.na(Age)) %>%
+     mutate(agecat = cut(Age, breaks = c(0, 14.99, 50, 150), 
+                         include.lowest = TRUE,
+                         labels = c("Under 15", "15 to 50",
+                                    "Over 50"))) %>%
+     group_by(Pclass,agecat,Sex) %>%
+     summarize(N=n(), survivors = sum(Survived))%>%
+     mutate(perc_survived = (signif((100*survivors/N), digits=8)))
> 
> print(titanic_4[1:6,])
# A tibble: 6 x 6
# Groups:   Pclass, agecat [3]
  Pclass   agecat    Sex     N survivors perc_survived
   <int>   <fctr>  <chr> <int>     <int>         <dbl>
1      1 Under 15 female     2         1      50.00000
2      1 Under 15   male     3         3     100.00000
3      1 15 to 50 female    70        68      97.14286
4      1 15 to 50   male    72        32      44.44444
5      1  Over 50 female    13        13     100.00000
6      1  Over 50   male    26         5      19.23077
> 

With regards to the Answer by Eric Fail, sprintf causes the column to change to character. This is an assignment for Swirl(), and swirl will not accept the type change.

> titanic_4 <- titanic %>% 
+     select(Survived, Pclass, Age, Sex) %>%
+     filter(!is.na(Age)) %>%
+     mutate(agecat = cut(Age, breaks = c(0, 14.99, 50, 150), 
+                         include.lowest = TRUE,
+                         labels = c("Under 15", "15 to 50",
+                                    "Over 50"))) %>%
+     group_by(Pclass,agecat,Sex) %>%
+     summarize(N=n(), survivors = sum(Survived))%>%
+     mutate(perc_survived = sprintf("%0.6f",(signif((100*survivors/N), digits=8))))
> 
> head (titanic_4)
# A tibble: 6 x 6
# Groups:   Pclass, agecat [3]
  Pclass   agecat    Sex     N survivors perc_survived
   <int>   <fctr>  <chr> <int>     <int>         <chr>
1      1 Under 15 female     2         1     50.000000
2      1 Under 15   male     3         3    100.000000
3      1 15 to 50 female    70        68     97.142857
4      1 15 to 50   male    72        32     44.444444
5      1  Over 50 female    13        13    100.000000
6      1  Over 50   male    26         5     19.230769

The suggestion to use option(digits=8) was successful. In order to get this suggestion to work, before running my code, I had to change the basic options of r so that it would round to the right number of digits. My r was set to round to 5.

> options(digits=8)
> titanic_4 <- titanic %>% 
+     select(Survived, Pclass, Age, Sex) %>%
+     filter(!is.na(Age)) %>%
+     mutate(agecat = cut(Age, breaks = c(0, 14.99, 50, 150), 
+                         include.lowest = TRUE,
+                         labels = c("Under 15", "15 to 50",
+                                    "Over 50"))) %>%
+     group_by(Pclass,agecat,Sex) %>%
+     summarize(N=n(), survivors = sum(Survived))%>%
+     mutate(perc_survived = (round((100*survivors/N),digits=6)))
> 
> head (titanic_4)
# A tibble: 6 x 6
# Groups:   Pclass, agecat [3]
  Pclass   agecat    Sex     N survivors perc_survived
   <int>   <fctr>  <chr> <int>     <int>         <dbl>
1      1 Under 15 female     2         1     50.000000
2      1 Under 15   male     3         3    100.000000
3      1 15 to 50 female    70        68     97.142857
4      1 15 to 50   male    72        32     44.444444
5      1  Over 50 female    13        13    100.000000
6      1  Over 50   male    26         5     19.230769   

Thank you very much for your comments and answers. Best wishes,

Drew

回答1:

sprintf(c(.8693683839, .7869698963), fmt='%#.6g')
#> [1] "0.869368" "0.786970"

and specifically for your case,

titanic_4 <- tibble(perc_survived = c(50.000000, 100.000000, 97.142857,
                                      44.444444, 100.000000, 19.230769))
titanic_4
#> # A tibble: 6 x 1
#>   perc_survived
#>           <dbl>
#> 1      50.00000
#> 2     100.00000
#> 3      97.14286
#> 4      44.44444
#> 5     100.00000
#> 6      19.23077
#> > 
> 
titanic_4 <- titanic_4 %>% mutate(perc_survived_6 = sprintf("%0.6f", perc_survived))
titanic_4
#> # A tibble: 6 x 2
#>   perc_survived perc_survived_6
#>           <dbl>           <chr>
#> 1      50.00000       50.000000
#> 2     100.00000      100.000000
#> 3      97.14286       97.142857
#> 4      44.44444       44.444444
#> 5     100.00000      100.000000
#> 6      19.23077       19.230769

or possible changing the global digits,

options(digits=8)
titanic_4
#> # A tibble: 6 x 1
#>   perc_survived
#>           <dbl>
#> 1     50.000000
#> 2    100.000000
#> 3     97.142857
#> 4     44.444444
#> 5    100.000000
#> 6     19.230769


回答2:

The answer to this question was given by Eric Fail on this page.

Changing the Global Digits options of the console using options(digits=8) solved the rounding problems in the head(). For a list of Global Options, visit this website. https://stat.ethz.ch/R-manual/R-devel/library/base/html/options.html

I had also created another post which showed how my console was rounding. G5W showed me how to fix the problem by adjusting the global digits.
How can I tell R to round correctly?

By default, the global digits in my r studio were set too low for me to correctly use round() or signf(). I needed to set the digits to 8 to achieve the correct rounding.

Thank you Eric Fail and G5W