如何在tidyr中正确使用spread函数

6

How do I change the following table from:

Type    Name    Answer     n
TypeA   Apple   Yes        5
TypeA   Apple   No        10
TypeA   Apple   DK         8
TypeA   Apple   NA        20
TypeA   Orange  Yes        6
TypeA   Orange  No        11
TypeA   Orange  DK         8
TypeA   Orange  NA        23

转换为:

Type    Name    Yes   No   DK   NA  
TypeA   Apple   5     10   8    20
TypeA   Orange  6     11   8    23

我使用以下代码获取第一个表格。
df_1 <- 
  df %>% 
  group_by(Type, Name, Answer) %>% 
  tally()  

然后我尝试使用spread命令来访问第二个表格,但是出现了以下错误信息:

"错误:所有列必须命名"

df_2 <- spread(df_1, Answer)
2个回答

6

根据ayk的评论,我提供一个例子。在我看来,当你有一个包含NA值的因子或字符类的列的data_frame时,如果不删除它们或重新分类数据,就无法进行spread。这是特定于data_frame(注意名称中带下划线的dplyr类)的,因为当你在data.frame中有NA值时,这个例子可以工作。例如,上面例子的稍微修改版本:

这是数据框:

library(dplyr)
library(tidyr)
df_1 <- data_frame(Type = c("TypeA", "TypeA", "TypeB", "TypeB"),
                   Answer = c("Yes", "No", NA, "No"),
                   n = 1:4)
df_1

这将生成一个数据框,看起来像这样

Source: local data frame [4 x 3]

   Type Answer     n
  (chr)  (chr) (int)
1 TypeA    Yes     1
2 TypeA     No     2
3 TypeB     NA     3
4 TypeB     No     4

然后,当我们尝试整理它时,会收到错误消息:
df_1 %>% spread(key=Answer, value=n)
Error: All columns must be named

但是如果我们去掉NA,那么它就“起作用”了:

df_1 %>%
    filter(!is.na(Answer)) %>%
    spread(key=Answer, value=n)
Source: local data frame [2 x 3]

   Type    No   Yes
  (chr) (int) (int)
1 TypeA     2     1
2 TypeB     4    NA

然而,移除 NAs 可能并不能给您期望的结果:即您可能想在整理后的表格中包含这些数据。您可以直接修改数据,将 NAs 更改为更具描述性的值。另外,您也可以将数据转换为 data.frame,然后进行展开操作:

as.data.frame(df_1) %>% spread(key=Answer, value=n)
   Type No Yes NA
1 TypeA  2   1 NA
2 TypeB  4  NA  3

1
这是非常有用的信息。感谢分享这些知识。8-) - ayk

5
我认为只需要使用 tidyr 就可以从 df_1 得到 df_2
library(magrittr)
df_1 <- read.csv(text="Type,Name,Answer,n\nTypeA,Apple,Yes,5\nTypeA,Apple,No,10\nTypeA,Apple,DK,8\nTypeA,Apple,NA,20\nTypeA,Orange,Yes,6\nTypeA,Orange,No,11\nTypeA,Orange,DK,8\nTypeA,Orange,NA,23", stringsAsFactors=F)

df_2 <- df_1 %>% 
  tidyr::spread(key=Answer, value=n)

输出:

   Type   Name DK No Yes NA
1 TypeA  Apple  8 10   5 20
2 TypeA Orange  8 11   6 23

这种方法在上面展示的代码中是有效的。然而,当第一个表格(即df_1)上的n列使用tally函数进行系统生成时,这种方法就不起作用了。它仍然会给我一个错误:所有列都必须命名。我用于使用tally生成n列的代码如上所述。看起来spread在这种情况下无法识别n列。还有其他建议吗? - ayk
想法1:在创建“df_1”的末尾使用dplyr :: ungroup()。 - wibeasley
想法2:使用as.data.frame()进行类型转换。想法3:使用dput()输出以便我们更好地查看结构。https://dev59.com/eG025IYBdhLWcg3whGSx。否则,很难看出您是如何得到`df_1`的。 - wibeasley
4
谢谢wibeasley。我终于明白为什么会收到“所有列必须命名”的消息了。这是因为在我的实际数据集中,存在NA值,当我进行spread操作时,它没有一个列名。我在示例数据集中没有包含NA,所以你没有看到我的问题。但不管怎样,很高兴问题现在得到解决。再次感谢你的帮助。8-) - ayk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接