我的数据框看起来像这样:
id val
1 a
1 b
2 a
2 c
2 d
3 a
3 a
将每一行视为一个标签val,用于带有id的观察。
我最终想要达到的目标是"共同出现"看起来像这样的矩阵,我得到每个字母与同一个字母在同一个id中出现的次数:
a b c d
a 1 1 1 1
b 1 0 0 0
c 1 0 0 1
d 1 0 1 0
我一直在绞尽脑汁想办法做到这一点,但到目前为止已经空洞。任何提示?最好使用tidyverse工具,但此时也可以使用其他选项。
编辑:在这种情况下,作为可能重复链接的问题的解决方案不起作用。我不确定为什么,但我怀疑它与那个有3列数据框的问题有关。
答案 0 :(得分:1)
这里是基地R的解决方案。不太优雅,但似乎有效
temp = data.frame(do.call(cbind, lapply(split(df, df$id), function(a)
combn(a$val, 2))), stringsAsFactors = FALSE)
sapply(sort(unique(df$val)), function(rows)
sapply(sort(unique(df$val)), function(cols)
sum(sapply(temp, function(x)
identical(sort(x), sort(c(rows, cols)))))))
# a b c d
#a 1 1 1 1
#b 1 0 0 0
#c 1 0 0 1
#d 1 0 1 0
或igraph
temp = t(do.call(cbind, lapply(split(df, df$id), function(a) combn(a$val, 2))))
library(igraph)
as.matrix(get.adjacency(graph(temp, directed = FALSE)))
# a c b d
#a 1 1 1 1
#c 1 0 0 1
#b 1 0 0 0
#d 1 1 0 0
数据强>
df = structure(list(id = c(1L, 1L, 2L, 2L, 2L, 3L, 3L),
val = c("a", "b", "a", "c", "d", "a", "a")),
.Names = c("id", "val"),
class = "data.frame",
row.names = c(NA, -7L))
答案 1 :(得分:0)
dplyr
+ purrr
的解决方案:
library(dplyr)
library(purrr)
df %>%
split(.$id) %>%
map_dfr(function(x){
t(combn(x$val, 2)) %>%
data.frame(stringsAsFactors = FALSE)
}) %>%
mutate_all(funs(factor(., levels = c("a", "b", "c", "d")))) %>%
table() %>%
pmax(., t(.))
<强>结果:强>
X2
X1 a b c d
a 1 1 1 1
b 1 0 0 0
c 1 0 0 1
d 1 0 1 0
备注:强>
df
分割为id
,然后使用map_dfr
中的purrr
将combn
函数映射到每个ID组。 combn
查找向量中的所有元素组合(长度(vec)选择2)并返回矩阵。 _dfr
末尾的map_dfr
表示结果将是按行绑定列表中每个元素的数据帧。所以这实际上是do.call(rbind, lapply())
。 mutate_all
确保table
保留所需的所有级别,即使列中不存在字母。table
步骤之后,产生了一个上三角矩阵,我将该矩阵及其转置输入pmax
pmax
从两个输入中找到并行最大值,并根据需要返回对称矩阵。数据:强>
df = read.table(text= "id val
1 a
1 b
2 a
2 c
2 d
3 a
3 a", header = TRUE, stringsAsFactors = FALSE)