我是R的新手 所以我不确定如何使用申请。 我想使用apply:
加快我的功能for(i in 1: ncol(exp)){
for (j in 1: length(fe)){
tmp =TRUE
id = strsplit(colnames(exp)[i],"\\.")
if(id == fe[j]){
tmp = FALSE
}
if(tmp ==TRUE){
only = cbind(only,c(names(exp)[i],exp[,i]) )
}
}
}
如何使用apply函数执行此操作?
编辑:
非常感谢您提供非常好的解释,并对我糟糕的描述感到抱歉。你猜对了一切,但是想要删除fe中的匹配。
Exp <- data.frame(A.x=1:10,B.y=10:1,C.z=11:20,A.z=20:11)
fe<-LETTERS[1:2]
然后结果应该只是'C'的名字。其他所有内容都应删除。
1 C.z
2 11
3 12
4 13
5 14
6 15
7 16
8 17
9 18
10 19
11 20
答案 0 :(得分:4)
编辑:如果您只想删除名称显示在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]
答案 1 :(得分:2)
apply()
系列函数是便捷函数。它们不一定比编写良好的for循环或矢量化函数更快。例如:
set.seed(21)
x <- matrix(rnorm(1e6),5e5,2)
system.time({
yLoop <- x[,1]*0 # preallocate result
for(i in 1:NROW(yLoop)) yLoop[i] <- mean(x[i,])
})
# user system elapsed
# 13.39 0.00 13.39
system.time(yApply <- apply(x, 1, mean))
# user system elapsed
# 16.19 0.28 16.51
system.time(yRowMean <- rowMeans(x))
# user system elapsed
# 0.02 0.00 0.02
identical(yLoop,yApply,yRowMean)
# TRUE
你的代码如此缓慢的原因是 - 正如Gavin所指出的那样 - 你在每次循环迭代中都在增长你的数组。在循环之前预先分配整个数组,您将看到显着的加速。