2015-03-17 3 views
4

Я хотел бы сделать кросс-вкладку в R, используя dplyr. У меня есть веские причины не просто использовать базовую команду table().dplyr cross tab с отсутствующими значениями

table(mtcars$cyl, mtcars$gear) 
    3 4 5 
    4 1 8 2 
    6 2 4 1 
    8 12 0 2 

library(dplyr) 
library(tidyr) 
mtcars %>% 
    group_by(cyl, gear) %>% 
    tally() %>% 
    spread(gear, n, fill = 0) 
Source: local data frame [3 x 4] 

    cyl 3 4 5 
1 4 1 8 2 
2 6 2 4 1 
3 8 12 0 2 

Это все хорошо и хорошо. Но он, кажется, разваливается, когда в значениях group_by() отсутствуют значения.

mtcars %>% 
    mutate(
    cyl = ifelse(cyl > 6, NA, cyl), 
    gear = ifelse(gear > 4, NA, gear) 
) %>% 
    group_by(cyl, gear) %>% 
    tally() 
Source: local data frame [8 x 3] 
Groups: cyl 

    cyl gear n 
1 4 3 1 
2 4 4 8 
3 4 NA 2 
4 6 3 2 
5 6 4 4 
6 6 NA 1 
7 NA 3 12 
8 NA NA 2 

# DITTO # %>% 
    spread(gear, n) 
Error in if (any(names2(x) == "")) { : 
    missing value where TRUE/FALSE needed 

Я думаю, что я хотел бы это для NA колонки, как, когда вы делаете table(..., useNA = "always"). Какие-нибудь советы?

+0

Могли бы вы просто заменить НО значащими ярлыками, такими как «cyl.NA». –

+0

Я полагаю, но перекрестные вкладки обычно исследуются сами по себе. Изучение того, как вы должны исследовать, кажется утомительным. Но, возможно, это необходимо. – gregmacfarlane

+1

Создайте минимальный воспроизводимый отчет об ошибках в реестре tidyr? – hadley

ответ

6

Одним из вариантов является замена наклейки NA. Это может быть легко достигнуто с mutate_each:

mtcars %>% 
    mutate(
    cyl = ifelse(cyl > 6, NA, cyl), 
    gear = ifelse(gear > 4, NA, gear) 
) %>% 
    group_by(cyl, gear) %>% 
    tally() %>% 
    ungroup() %>% 
    mutate_each(funs(replace(., is.na(.), 'missing'))) %>% 
    spread(gear, n) 

#  cyl 3 4 missing 
# 1  4 1 8  2 
# 2  6 2 4  1 
# 3 missing 12 NA  2 
+1

Мне нравится это и пойдет с ним на данный момент, но я думаю, что более постоянное решение должно пройти через ' исправление ошибки tidyr. – gregmacfarlane

1

Согласовано, что окончательное решение это должно быть tidyr исправить ошибку, но в то же время, это можно обойти путем сбрасывания dplyr tbl_df формат:

mtcars %>% 
    mutate(
    cyl = ifelse(cyl > 6, NA, cyl), 
    gear = ifelse(gear > 4, NA, gear) 
) %>% 
    group_by(cyl, gear) %>% 
    tally() %>% 
    data.frame() %>% ### <-- go from tbl_df to data.frame 
    spread(gear, n) 

    cyl 3 4 NA 
1 4 1 8 2 
2 6 2 4 1 
3 NA 12 NA 2 

Добавление вызова data.frame() позволяет запустить код, хотя он создает столбец с именем NA, поэтому это, вероятно, лучше всего подходит для исследовательских анализов, которые печатаются на консоли.