【发布时间】:2018-11-19 17:19:27
【问题描述】:
我有一个包含 3 个分类变量 (x,y,z) 以及一个 ID 列的数据框:
df <- frame_data(
~id, ~x, ~y, ~z,
1, "a", "c" ,"v",
1, "b", "d", "f",
2, "a", "d", "v",
2, "b", "d", "v")
我想将spread() 应用于ID 的每个分类变量组。
输出应该是这样的:
id a b c d v f
1 1 1 1 1 1 1
2 1 1 0 2 2 0
我尝试过这样做,但我一次只能为一个变量而不是全部一起这样做。
例如:仅对y 列应用展开(类似地,可以分别对x 和z 进行)但不能在一行中一起使用
df %>% count(id,y) %>% spread(y,n,fill=0)
# A tibble: 2 x 3
id c d
<dbl> <int> <int>
1.00 1 1
2.00 0 2
分三步解释我的代码:
第1步:计数频率
df %>% count(id,y)
id y n
<dbl> <chr> <int>
1.00 c 1
1.00 d 1
2.00 d 2
第二步:申请spread()
df %>% count(id,y) %>% spread(y,n)
# A tibble: 2 x 3
id c d
<dbl> <int> <int>
1 1.00 1 1
2 2.00 NA 2
第 3 步:添加 fill = 0 ,替换 NA,这意味着在 id 2 的 y 列中 c 的出现次数为零(如您在 df 中看到的那样)
df %>% count(id,y) %>% spread(y,n,fill=0)
# A tibble: 2 x 3
id c d
<dbl> <int> <int>
1.00 1 1
2.00 0 2
问题:在我的实际数据集中,我有20个这样的分类变量,我不能一一做。我希望一次完成所有工作。
是否可以将spread() 应用于tidyr 中的所有分类变量?如果不能,请您提出替代方案
注意:我也尝试了这些答案,但对这种特殊情况没有帮助:
- R spreading multiple columns with tidyr
- Is it possible to use spread on multiple columns in tidyr similar to dcast?
- Can spread() in tidyr spread across multiple value?
- Expanding columns associated with a categorical variable into multiple columns with dplyr/tidyr while retaining id variable
其他相关的有用问题:
两个分类列(例如:调查数据集)可能具有相同的值。如下所示。
df <- frame_data(
~id, ~Do_you_Watch_TV, ~Do_you_Drive,
1, "yes", "yes",
1, "yes", "no",
2, "yes", "no",
2, "no", "yes")
# A tibble: 4 x 3
id Do_you_Watch_TV Do_you_Drive
<dbl> <chr> <chr>
1 1.00 yes yes
2 1.00 yes no
3 2.00 yes no
4 2.00 no yes
运行以下代码不会区分“Do_you_Watch_TV”、“Do_you_Drive”的“是”和“否”:
df %>% gather(Key, value, -id) %>%
group_by(id, value) %>%
summarise(count = n()) %>%
spread(value, count, fill = 0) %>%
as.data.frame()
id no yes
1 1 3
2 2 2
Whereas, expected output should be :
id Do_you_Watch_TV_no Do_you_Watch_TV_yes Do_you_Drive_no Do_you_Drive_yes
1 0 2 1 1
2 1 1 1 1
所以,我们需要通过添加前缀来分别处理 Do_you_Watch_TV 和 Do_you_Drive 中的 No 和 Yes。 Do_you_Drive_yes , Do_you_Drive_no , Do_you_Watch_TV _yes , Do_you_Watch_TV _no 。
我们怎样才能做到这一点?
谢谢
【问题讨论】:
-
嗨@Jaap:上面的问题有两个部分。 第一部分由你在这里回答部分:[链接]stackoverflow.com/questions/43262085/…。您的代码建议在 collect 中明确提及列:
tidyr :: spread library(dplyr) library(tidyr) dat %>% gather(key, val, state:type2) %>% group_by(serialno, val) %>% tally() %>% spread(val, n, fill = 0)而我正在寻找隐含的方式。所以,我们可以用gather(Key, value, -serialno)代替gather(Key, value, state:type2) -
@JAAP 第二部分是:如果我们有一个附加条件,我们如何做同样的事情 - 如果两个不同的类别列具有相同的值? 答案也是不在这里 [链接] stackoverflow.com/questions/43262085/… 。所以,这个问题可能不是重复的。这两部分都在下面回答了
-
感谢您添加第二个链接,但这是否涵盖使用
tidyr::spread()?如果有的话,你可以在这里添加链接吗?第一个链接部分回答。第二个链接:使用dcast()我的问题与使用tidyr::spread()相关,因为它的性能优于dcast()(执行时间)。请查看我的标题和问题 -
(1) 第一个链接完全回答了您问题的第一部分。
gather(Key, value, state:type2)与gather(Key, value, -serialno)、see here 相同。 (2) 两个附加链接涵盖了您问题的第二部分。
标签: r dataframe dplyr tidyr data-cleaning