我正在尝试根据数据表中的列(路径)提出多个列。我的数据集目前有600万行。
编辑:包含天真的最小数据集
set.seed(24);
DATA <- data.frame(path=paste0(sample(LETTERS[1:3], 25, replace=TRUE),">",sample(LETTERS[1:3], 25, replace=TRUE)), value=rnorm(25))
以下是我目前正在使用的代码(当然我不是在使用字母表):
for (i in 1:nrow(DATA)) {
if(grepl("A", DATA$path[i])){DATA$A[i]=1}else{DATA$A[i]=0}
if(grepl("B", DATA$path[i])){DATA$B[i]=1}else{DATA$B[i]=0}
if(grepl("C", DATA$path[i])){DATA$C[i]=1}else{DATA$C[i]=0}
}
我使用的旧版代码是:
DATA$A <- sapply(DATA$path, function(x) { if(grepl("A", x)){1}else{0}})
DATA$B <- sapply(DATA$path, function(x) { if(grepl("B", x)){1}else{0}})
我要输出的每一列。
但这种效率非常低,因为它太多次了。
我的问题是:是否有更有效的方法来做同样的事情?还是我坚持使用第一个代码块?
提前致谢!
答案 0 :(得分:2)
我们可以split
路径&#39; >
列,并获取该列中的unique
元素(&#39; Un1&#39;)。循环过来&#39; Un1&#39;并使用grepl
查找匹配项。
Un1 <- sort(unique(unlist(strsplit(as.character(DATA$path), '>'))))
DATA[Un1] <- lapply(Un1, function(x) as.integer(grepl(x, DATA$path)))
或另一种选择是在mtabulate
输出qdapTools
上使用strsplit
,否定(!
)将0
转换为&#39; TRUE&# 39;和所有其他值为“FALSE&#39;”,再次否定,以便&#39; FALSE&#39;成为&#39; TRUE&#39;反之亦然,用+(
包装它来强制逻辑到整数。我们也可以使用as.integer
或+0L
等。
library(qdapTools)
cbind(DATA, +(!!mtabulate(strsplit(as.character(DATA$path), '>')) ))
或者在分开“路径”之后我们可以循环列,应用model.matrix
并将|
与Reduce
一起使用
d1 <- do.call(rbind.data.frame,strsplit(as.character(DATA$path), '>'))
names(d1) <- paste0('path', 1:2)
cbind(DATA, +(Reduce(`|`,lapply(d1, function(x) model.matrix(~0+x)))))
答案 1 :(得分:1)
为什么不简单:
DATA$A = grepl('A', DATA$path) + 0L