I am trying to use summarize, where the vector being summarized has names. The summarize function copies these names to the output, but the length is now wrong. When I try to format the resulting summary, the incorrect length of the names attribute throws an error.
In the example I really care about, the vector with names is the fitted.values from a glm model. I don't want the names, but they come for free. The toy example below uses mtcars.
``` r
library(tidyverse)
#> -- Attaching packages -------------------------------------------------------------------------------- tidyverse 1.2.1 --
#> v ggplot2 2.2.1 v purrr 0.2.4
#> v tibble 1.4.1 v dplyr 0.7.4
#> v tidyr 0.7.2 v stringr 1.2.0
#> v readr 1.1.1 v forcats 0.2.0
#> -- Conflicts ----------------------------------------------------------------------------------- tidyverse_conflicts() --
#> x dplyr::filter() masks stats::filter()
#> x dplyr::lag() masks stats::lag()
# create a copy of mtcars, with the original mpg and a copy with names
namedmpg <- mtcars$mpg
attr(namedmpg, "names") <- row.names(mtcars)
MTCARS <- bind_cols(mtcars, namedmpg = namedmpg)
When I use the original mpg variable I get exactly what I want.
goodframe <- summarize(group_by(MTCARS, cyl), meanmpg = mean(mpg))
goodframe # gives exactly what we want
#> # A tibble: 3 x 2
#> cyl meanmpg
#> <dbl> <dbl>
#> 1 4.00 26.7
#> 2 6.00 19.7
#> 3 8.00 15.1
format(goodframe$meanmpg) # formats fine
#> [1] "26.66364" "19.74286" "15.10000"
Now use the named mpg instead.
badframe <- summarize(group_by(MTCARS, cyl), meanmpg = mean(namedmpg))
badframe # seems to have what we want
#> # A tibble: 3 x 2
#> cyl meanmpg
#> <dbl> <dbl>
#> 1 4.00 26.7
#> 2 6.00 19.7
#> 3 8.00 15.1
format(badframe$meanmpg) # throws an error
#> Error in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L, : 'names' attribute [32] must be the same length as the vector [3]
names(badframe$meanmpg) # the original names, which are now too many
#> [1] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710"
#> [4] "Hornet 4 Drive" "Hornet Sportabout" "Valiant"
#> [7] "Duster 360" "Merc 240D" "Merc 230"
#> [10] "Merc 280" "Merc 280C" "Merc 450SE"
#> [13] "Merc 450SL" "Merc 450SLC" "Cadillac Fleetwood"
#> [16] "Lincoln Continental" "Chrysler Imperial" "Fiat 128"
#> [19] "Honda Civic" "Toyota Corolla" "Toyota Corona"
#> [22] "Dodge Challenger" "AMC Javelin" "Camaro Z28"
#> [25] "Pontiac Firebird" "Fiat X1-9" "Porsche 914-2"
#> [28] "Lotus Europa" "Ford Pantera L" "Ferrari Dino"
#> [31] "Maserati Bora" "Volvo 142E"
So I have to do something to get the summary in a form usable for further processing. Here is one hack.
format(badframe$meanmpg + 0) # a real hack, but seems to work
Of course there is always the old fashioned way
stillgood <- with(MTCARS, aggregate(namedmpg, list(cyl), mean))
stillgood
#> Group.1 x
#> 1 4 26.66364
#> 2 6 19.74286
#> 3 8 15.10000
format(stillgood$x) # works
#> [1] "26.66364" "19.74286" "15.10000"
```
I am not sure if the situation is a bug or a feature. IMHO it should be documented either way.
In addition to the hack above, I could kill the names before the summarize. But I might want them someday.
Is there a better way?