tidyr 扩展函数在预期紧凑向量时生成稀疏矩阵
Posted
技术标签:
【中文标题】tidyr 扩展函数在预期紧凑向量时生成稀疏矩阵【英文标题】:tidyr spread function generates sparse matrix when compact vector expected 【发布时间】:2015-02-14 14:00:51 【问题描述】:我正在学习 dplyr,来自 plyr,我想从 xtabs 的输出中生成(每组)列(每交互)。
简短的总结:我明白了
A B
1 NA
NA 2
当我想要的时候
A B
1 2
xtabs 数据如下所示:
> xtabs(data=data.frame(P=c(F,T,F,T,F),A=c(F,F,T,T,T)))
A
P FALSE TRUE
FALSE 1 2
TRUE 1 1
现在do(
想要它的数据在数据框中,像这样:
> xtabs(data=data.frame(P=c(F,T,F,T,F),A=c(F,F,T,T,T))) %>% as.data.frame
P A Freq
1 FALSE FALSE 1
2 TRUE FALSE 1
3 FALSE TRUE 2
4 TRUE TRUE 1
现在我想要一个单行输出,其中列是级别的交互。这就是我要找的东西:
FALSE_FALSE TRUE_TRUE FALSE_TRUE TRUE_FALSE
1 1 2 1
但是我得到了
> xtabs(data=data.frame(P=c(F,T,F,T,F),A=c(F,F,T,T,T))) %>%
as.data.frame %>%
unite(S,A,P) %>%
spread(S,Freq)
FALSE_FALSE FALSE_TRUE TRUE_FALSE TRUE_TRUE
1 1 NA NA NA
2 NA 1 NA NA
3 NA NA 2 NA
4 NA NA NA 1
我显然在这里误解了一些东西。我在这里寻找 reshape2 的等效代码(使用 magrittr 管道保持一致性):
> xtabs(data=data.frame(P=c(F,T,F,T,F),A=c(F,F,T,T,T))) %>%
as.data.frame %>% # can be omitted. (safely??)
melt %>%
mutate(S=interaction(P,A),value=value) %>%
dcast(NA~S)
Using P, A as id variables
NA FALSE.FALSE TRUE.FALSE FALSE.TRUE TRUE.TRUE
1 NA 1 1 2 1
(注意这里使用了NA,因为在这个简化的例子中我没有分组变量)
更新 - 有趣的是,添加单个分组列似乎可以解决这个问题 - 为什么它在我不告诉它的情况下合成(可能来自 row_name)一个分组列?
> xtabs(data=data.frame(h="foo",P=c(F,T,F,T,F),A=c(F,F,T,T,T))) %>%
as.data.frame %>%
unite(S,A,P) %>%
spread(S,Freq)
h FALSE_FALSE FALSE_TRUE TRUE_FALSE TRUE_TRUE
1 foo 1 1 2 1
这似乎是部分解决方案。
【问题讨论】:
This 似乎是同一个问题。 @Henrik:确实如此。 This 反过来也是同样的问题,Hadley 给出了解释性评论。正如您在更新中发现的那样,这两个输出在正确的上下文中都是有意义的。当上下文只是隐式时,spread()
必须猜测。
@nacnudus:感谢您的帮助。我不同意这种情况——我没有发现扩展的情况是有道理的——只是它存在。在没有可供猜测的参数/列的情况下,我的期望是它将假设存在一个单一的全局身份。你能解释一下为什么这可能不是真的吗?
好吧,我也杀了我的反驳评论:-)
【参考方案1】:
这里的关键是spread
不聚合数据。
因此,如果您还没有先使用 xtabs
进行聚合,您会这样做:
a <- data.frame(P=c(F,T,F,T,F),A=c(F,F,T,T,T), Freq = 1) %>%
unite(S,A,P)
a
## S Freq
## 1 FALSE_FALSE 1
## 2 FALSE_TRUE 1
## 3 TRUE_FALSE 1
## 4 TRUE_TRUE 1
## 5 TRUE_FALSE 1
a %>% spread(S, Freq)
## FALSE_FALSE FALSE_TRUE TRUE_FALSE TRUE_TRUE
## 1 1 NA NA NA
## 2 NA 1 NA NA
## 3 NA NA 1 NA
## 4 NA NA NA 1
## 5 NA NA 1 NA
这在任何其他方面都没有意义(没有聚合)。
这可以根据fill
参数的帮助文件进行预测:
如果其他变量的每个组合都没有值 和键列,这个值将被替换。
在您的情况下,没有任何其他变量可以与键列组合。如果有的话……
b <- data.frame(P=c(F,T,F,T,F),A=c(F,F,T,T,T), Freq = 1
, h = rep(c("foo", "bar"), length.out = 5)) %>%
unite(S,A,P)
b
## S Freq h
## 1 FALSE_FALSE 1 foo
## 2 FALSE_TRUE 1 bar
## 3 TRUE_FALSE 1 foo
## 4 TRUE_TRUE 1 bar
## 5 TRUE_FALSE 1 foo
> b %>% spread(S, Freq)
## Error: Duplicate identifiers for rows (3, 5)
...它会失败,因为它不能聚合第 3 行和第 5 行(因为它不是这样设计的)。
tidyr
/dplyr
的方法是group_by
和summarize
而不是xtabs
,因为summarize
保留了分组列,因此spread
可以判断哪些观察属于同一行:
b %>% group_by(h, S) %>%
summarize(Freq = sum(Freq))
## Source: local data frame [4 x 3]
## Groups: h
##
## h S Freq
## 1 bar FALSE_TRUE 1
## 2 bar TRUE_TRUE 1
## 3 foo FALSE_FALSE 1
## 4 foo TRUE_FALSE 2
b %>% group_by(h, S) %>%
summarize(Freq = sum(Freq)) %>%
spread(S, Freq)
## Source: local data frame [2 x 5]
##
## h FALSE_FALSE FALSE_TRUE TRUE_FALSE TRUE_TRUE
## 1 bar NA 1 NA 1
## 2 foo 1 NA 2 NA
【讨论】:
但是在对最大身份集进行分组时与 dplyr 组结合使用时,我们有一个隐含的聚合:iirc 实际上不能正确运行。 什么是最大身份集?我认为除了提供虚拟分组变量之外别无选择。您可以在原始数据框中执行此操作,也可以在spread
之前执行group_by(1)
,然后在之后执行select(-
1)
。
我的意思是一旦除键和值之外的所有变量都在 group_by 操作中被用作“枚举器”。还是谢谢
@nacnudus 我只是想说你对group_by(1)
的评论对我很有帮助。以上是关于tidyr 扩展函数在预期紧凑向量时生成稀疏矩阵的主要内容,如果未能解决你的问题,请参考以下文章