当紧凑向量期望时,tidyr扩展函数生成稀疏矩阵

Ale*_*own 11 r dplyr tidyr

我正在学习dplyr,来自plyr,我想从xtabs的输出生成(每组)列(每个交互).

简短摘要:我收到了

A    B
1    NA
NA   2
Run Code Online (Sandbox Code Playgroud)

当我想要的时候

A    B
1    2
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

现在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
Run Code Online (Sandbox Code Playgroud)

现在我想要一个单行输出,其中列是级别的交互.这是我正在寻找的:

FALSE_FALSE TRUE_TRUE FALSE_TRUE TRUE_FALSE
          1         1          2          1
Run Code Online (Sandbox Code Playgroud)

但相反,我得到了

> 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
Run Code Online (Sandbox Code Playgroud)

我显然在这里误解了一些东西.我在这里寻找相当于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
Run Code Online (Sandbox Code Playgroud)

(注意这里使用了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
Run Code Online (Sandbox Code Playgroud)

这似乎是一个部分解决方案.

nac*_*dus 6

这里的关键是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
Run Code Online (Sandbox Code Playgroud)

任何其他方式都没有意义(没有聚合).

这是基于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)
Run Code Online (Sandbox Code Playgroud)

...它会失败,因为它无法聚合第3行和第5行(因为它不是为了设计).

tidyr/ dplyr办法做到这将是group_bysummarize不是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
Run Code Online (Sandbox Code Playgroud)