dplyr交叉表缺少值

时间:2015-03-17 19:52:11

标签: r dplyr tidyr

我想使用dplyr在R中制作一个交叉表。我有充分的理由不仅使用基础table()命令。

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")一样。有什么提示吗?

2 个答案:

答案 0 :(得分:8)

一种选择是用标签替换NA s。这可以通过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 :(得分: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的列,因此这可能最适合打印到控制台的探索性分析。