编辑:如果您只想删除名称出现在 fe 中的列,您可以简单地执行以下操作:
Exp <- data.frame(A.x=1:10,B.y=10:1,C.z=11:20,A.z=20:11)
fe<-LETTERS[1:2]
id <- sapply(strsplit(names(Exp),"\\."),
function(i)!i[1] %in% fe)
Exp[id]
这段代码和你的(更新的)for循环一样,只是效率更高。您不必循环遍历 fe,该%in%
函数是矢量化的。
如果名称可以出现在点之间的任何位置,则
id <- sapply(strsplit(names(Exp),"\\."),
function(i)sum(i %in% fe)==0)
你的代码做了一些非常有趣的事情,我不知道你到底想做什么。一方面,strsplit
给出一个列表,所以id == fe[j]
总是返回 false,除非fe[j]
是一个列表本身。而且我怀疑它是...所以我将您的代码更正为
id = strsplit(colnames(Exp)[i],"\\.")[[1]][1]
如果您想与点之前的所有内容进行比较,或者
id = unlist(strsplit(colnames(Exp)[i],"\\."))
如果您想与字符串中的所有内容进行比较。在这种情况下,您也应该使用%in%
而不是==
。
其次,你得到的是一个字符矩阵,它本质上乘以行。如果 fe[j] 中的所有元素都是唯一的,您也可以这样做:
only <- rbind(names(exp),exp)
only <- do.call(cbind,lapply(mat,function(x)
matrix(rep(x,ncol(exp)-1),nrow=nrow(exp)+1)
))
假设您的代码中的逻辑确实有意义(因为您没有应用一些不可能知道的示例数据),优化运行:
mat <- rbind(names(Exp),Exp)
do.call(cbind,
lapply(mat, function(x){
n <- sum(!fe %in% strsplit(x[1],"\\.")[[1]][1])
matrix(rep(x,n),nrow=nrow(mat))
}))
请注意 - 如果您对 fe[j] 出现在名称中的任何位置感兴趣 - 您可以将代码更改为:
do.call(cbind,
lapply(mat, function(x){
n <- sum(!fe %in% unlist(strsplit(x[1],"\\.")))
matrix(rep(x,n),nrow=nrow(mat))
}))
如果这没有返回您想要的,那么您的代码也不会这样做。我检查了以下示例数据,并且都给出了相同的结果:
Exp <- data.frame(A.x=1:10,B.y=10:1,C.z=11:20,A.z=20:11)
fe <- LETTERS[1:4]