set.seed(1)
names <- letters[1:3]
df <-
data.frame(id = LETTERS[1:5]
names = replicate(5,paste0(sample(names, sample(1:3)),collapse = ',')),
stringsAsFactors = F)
然后df
中的每个ID都与1-3个名称相关联。
> df
id names
1 A a
2 B b,c
3 C c,b
4 D c
5 E b,c
如何有效地填充矩阵(在我们的示例中为5x3),其中0(#name in not row)和1&#39; (行名)。矩阵看起来像:
res <-
matrix(nrow = nrow(df), ncol = length(names),
dimnames = list(df$id, names), data = 0)
> res
a b c
A 0 0 0
B 0 0 0
C 0 0 0
D 0 0 0
E 0 0 0
第一行是(1,0,0),第二行是(0,1,1)等。
答案 0 :(得分:3)
我们可以在table
分割'名称'之后使用,
,并stack
将list
输出分割为data.frame
。
table(stack(setNames(strsplit(df$names, ","), df$id))[2:1])
# values
#ind a b c
# A 1 0 0
# B 0 1 1
# C 0 1 1
# D 0 0 1
# E 0 1 1
分割“名称”列后,mtabulate
的其他选项为qdapTools
。
library(qdapTools)
mtabulate(setNames(strsplit(df$names, ","), df$id))
# a b c
#A 1 0 0
#B 0 1 1
#C 0 1 1
#D 0 0 1
#E 0 1 1
如果我们使用的是dplyr/tidyr
,则有一个选项是separate_rows/spread
library(dplyr)
library(tidyr)
separate_rows(df, names) %>%
mutate(v1 = 1) %>%
spread(names, v1, fill = 0)
# id a b c
#1 A 1 0 0
#2 B 0 1 1
#3 C 0 1 1
#4 D 0 0 1
#5 E 0 1 1
或者我们可以在分割后使用dcast
中的data.table
library(data.table)
dcast(setDT(df)[, strsplit(names, ","), id], id ~V1, length)
df <- structure(list(id = c("A", "B", "C", "D", "E"), names = c("a",
"b,c", "c,b", "c", "b,c")), .Names = c("id", "names"),
class = "data.frame", row.names = c("1", "2", "3", "4", "5"))