(评论太长了)
我怀疑这是可能的(虽然不能肯定地说)。
两个挑战:
- 在长格式中,每个唯一的“模式”至少分布
ncol
在行上。您将如何使用“总结”并将其分解为一行(它只能保存一个值,这意味着它是一个不完整的模式)?
- 我在您的示例代码中看到的第二个问题:当您创建 df2 并使用时,
filter(value > 0)
您有效地破坏了大多数现有模式,因为绝大多数模式(宽格式)在某些行中包含 0。那时您仍然可以观察到的唯一完整模式可能仅包含 1,对吗?
更准确地说:这可能是可能的,但我相信它需要比从长到宽的转换更大的解决方法。
我只是改变了主意,但我不确定这与从长格式到宽格式的转换是否真的有很大不同:
out2 <- group_by(df2, id) %>% arrange(id, variable) %>%
summarise(pattern = toString(value)) %>%
count(pattern)
结果:
> out2 %>% arrange(desc(n))
Source: local data frame [896 x 2]
pattern n
1 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 2794
2 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 2754
3 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 2742
4 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 2716
5 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 2716
6 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 2710
7 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 2685
8 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 2633
9 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 2630
10 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 2618
.. ... ...
为了与其他数据进行比较并生成df2
,我使用:
set.seed(100)
ncol <- 10
nrow <- 100000
#create sample matrix in wide format
df1 <- as.data.frame(matrix((runif(nrow*ncol)>0.8) + 0, ncol=ncol))
cols <- colnames(df1)
df1 <- filter(df1, rowSums(df1)>0)
df1 <- cbind(id=seq_len(nrow(df1)), df1)
#compute frequency of patterns
out1 <- df1 %>%
group_by_(.dots=cols) %>% summarise(freq=n()) %>% as.data.frame() %>% arrange(desc(freq))
#convert to deep format
df2 <- df1 %>% # this is the input for my code
gather(variable, value, -id) # note that I don't use `filter(value>0)` here!
与 out1 比较:
> head(out1[order(-out1$freq),])
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 freq
1 0 0 0 0 0 0 0 1 0 0 2794
2 0 0 1 0 0 0 0 0 0 0 2754
3 0 0 0 0 0 0 0 0 0 1 2742
4 0 0 0 0 0 0 0 0 1 0 2716
5 0 0 0 0 0 1 0 0 0 0 2716
6 1 0 0 0 0 0 0 0 0 0 2710
显然,我不能identical(out1, out2)
在这里使用,因为out2
只有 2 列.. 但我可以在频率计数上使用它:
identical(out1$freq, out2$n)
#[1] TRUE
.. 如果你想将 out2 转换为与 out1 相同的东西,你可以separate
从 tidyr 使用:
separate(out2, col = pattern, into = paste0("V", seq_len(ncol)), sep = ",")