我有一个数据框,其中包含许多针对由|:
分隔的id的功能df = data.frame(id = c("1","2","3"),
features = c("1|2|3","4|5","6|7")
)
df
我的目标是为每个功能添加一个列,并指示其存在的ID,例如
id | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 1 | 1 | 0 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
这些功能存储在一个不同的表中,因此可以使用完整的可能功能列表,但如果我能动态生成这些功能会更好。
我的第一次尝试是使用一个非常慢的for循环,grepl()填充预先创建的矩阵'm',例如。
for (i in 1:dim(df)[1]){
print(i)
if(grepl("1\\|", df$feature[i])) {m[i,1] <- 1}
if(grepl("2\\|", df$feature[i])) {m[i,2] <- 1}
if(grepl("3\\|", df$feature[i])) {m[i,3] <- 1}
if(grepl("4\\|", df$feature[i])) {m[i,4] <- 1}
if(grepl("5\\|", df$feature[i])) {m[i,5] <- 1}
if(grepl("6\\|", df$feature[i])) {m[i,6] <- 1}
if(grepl("7\\|", df$feature[i])) {m[i,7] <- 1}
}
当功能进入青少年时,忽略了我的正则表达式会崩溃的事实。在我需要运行它的~400,000行时,这非常慢。另外,我需要为每个id创建一个if()而不是动态地发生这种情况。
有没有办法用动态列生成更简洁地做到这一点?
答案 0 :(得分:1)
要返回的最自然的对象是矩阵。这是在基础R中执行此操作的方法。
# split features column by pipe symbol and subset result, dropping pipes
temp <- lapply(strsplit(as.character(df$features), split="|"), function(i) i[i != "|"])
# use %in% to return logical vector of desired length, convert to integer and rbind list
myMat <- do.call(rbind, lapply(temp, function(i) as.integer(1:7 %in% i)))
# add id as row names
rownames(myMat) <- df$id
返回
myMat
[,1] [,2] [,3] [,4] [,5] [,6] [,7]
1 1 1 1 0 0 0 0
2 0 0 0 1 1 0 0
3 0 0 0 0 0 1 1
如果您真的需要data.frame,可以使用
temp <- lapply(strsplit(as.character(df$features), split="|"), function(i) i[i != "|"])
myDf <- cbind(id=df$id, data.frame(do.call(rbind,
lapply(temp, function(i) as.integer(1:7 %in% i)))))
返回
myDf
df$id X1 X2 X3 X4 X5 X6 X7
1 1 1 1 1 0 0 0 0
2 2 0 0 0 1 1 0 0
3 3 0 0 0 0 0 1 1
答案 1 :(得分:0)
使用stringr
和dplyr
的@Imo解决方案的不同实现,用于更紧凑的表示法,适用于从1到任意数字的功能:
# Split the feature column
temp <- str_split(df$features, "\\|")
# Find the maximum feature
maximum <- as.numeric(max(do.call(rbind, temp), na.rm = T))
# Crate the final data frame
lapply(temp, function(i) as.integer(1:maximum %in% i)) %>%
do.call(rbind,.) %>%
as.data.frame() %>%
cbind(df, .)
产生:
id features V1 V2 V3 V4 V5 V6 V7
1 1 1|2|3 1 1 1 0 0 0 0
2 2 4|5 0 0 0 1 1 0 0
3 3 6|7 0 0 0 0 0 1 1