[英]R Apply functions to lists with lapply
我有三个列表,List1包含标识符,List2包含逗号分隔的字符串(可能是List1中的项目),List3包含数字(一些测得的分数)。
List1=c("Object1","Object2",......,"Objectn")
List2=c("Object1","Object2,Object3","Object4","Object5","Object6", .... )
List3=c("0.90","0,80",....)
所有列表的长度相同。
对于List1中的每个项目,List2中的每个项目,我想做什么,请检查交集是否不为null,并增加一个分数。
我可以迭代地执行此操作,但是由于我的列表太长,因此我希望使用lapply进行操作,但失败了。 任何帮助,将不胜感激。
FinalScoreList="",
for(i in 1:length(List1)){
score=0
for(j in 1:length(List2)){
if(length(intersect(List1[[i]],
as.list(unlist(strsplit(as.character(List2[j]),',')))))>0) {
score=score+as.double(List3[j])
}
}
FinalScoreList=c(FinalScoreList,score)
}
我认为这是您追求的目标:
List1=c("Object1","Object2", "0.70")
List2=c("Object1","Object2", "Object3")
List3=c("0.90","0,80", "0.70")
# Make a list of lists
All_Lists = list(
"List1" = List1,
"List2" = List2,
"List3" = List3
)
# Create a dataframe listing all pairwise combinations of the lists
intersect_df <- data.frame(t(combn(names(All_Lists), 2)))
# Add a new column to this dataframe indicating the length of the intersection
# between each pair of lists
intersect_df$count <- apply(intersect_df, 1, function(r) length(intersect(All_Lists[[r[1]]], All_Lists[[r[2]]])))
输出:
> intersect_df
X1 X2 count
1 List1 List2 2
2 List1 List3 1
3 List2 List3 0
因此,输出中的每一行都指定两个列表( X1
和X2
)的组合,并且列count
指示这两个列表之间的交点长度。
首先,我不建议将非列表项的名称命名为“列表”(List1,List2,List3 ...)。 其次,因为您希望“ List3”元素为数字,所以请从头开始。 我创建了以下示例:
library(dplyr)
List1=c("Object1","Object2","Object3","Object4","Object5","Object6","Object7","Object8")
List2=c("Object3","Object4","Object5","Object6","Object7","Object8","Object9","Object10")
List3=c("0.90","0.80","0.70","0.60","0.50","0.40","0.30","0.20")%>%as.numeric
现在,在您的代码中进行了少量更改,我们得到了FinalScoreList
FinalScoreList=c()
for(i in 1:length(List1)){
score=0
for(j in 1:length(List2)){
if(length(intersect(List1[[i]], as.list(unlist(strsplit(as.character(List2[j]),',')))))>0) {
score=score+List3[j]
}
}
FinalScoreList=c(FinalScoreList,score)
}
> FinalScoreList
[1] 0.0 0.0 0.9 0.8 0.7 0.6 0.5 0.4
我们可以得到相同的结果而无需循环下面的代码:
df=data.frame(List1,List2,List3)
df$Matches<-0
matches0<-grep(List1,pattern=paste(intersect(List2,List1),collapse="|"))
matches1<-grep(List2,pattern=paste(intersect(List2,List1),collapse="|"))
df$Matches[matches0]<-List3[matches1]
> df$Matches
[1] 0.0 0.0 0.9 0.8 0.7 0.6 0.5 0.4
您可以在循环之前执行List2
的拆分,这已经加快了速度。 同样,从空向量FinalScoreList
开始时,R必须在每个步骤中都增大它,这也会使其变慢。
这是嵌套lapply
/ sapply
的解决方案:
List2 <- lapply(List2, function(x) unlist(strsplit(x, split = ",")))
FinalScoreList <- lapply(List1, function(x) {
indicator <- sapply(List2, function(y) x %in% y)
sum(List3[indicator])
})
unlist(FinalScoreList)
正如@Antonis已经说过的,您应该已经将List3
向量存储为数字向量。
数据
List1 <- paste0("Object", 1:10)
List2 <- c("Object1", "Object6,Object5", "Object2,Object1", "Object7",
"Object6,Object8", "Object5,Object9", "Object4,Object2",
"Object3,Object8", "Object2,Object6", "Object10,Object3")
List3 <- runif(10)
感谢大伙们。
现在假设List1与List2具有相同的性质,即项目可以是串联的字符串。 并且也可以具有不同的长度。
我确实在List1上执行了strsplit,但仍然在FinalScoreList中获得了NA。
List1 <- c("Object1", "Object7,Object5", "Object2,Object1")
List2 <- c("Object1", "Object6,Object5", "Object0,Object1", "Object7",
"Object6,Object8", "Object5,Object9", "Object4,Object2",
"Object3,Object8", "Object2,Object3", "Object10,Object3")
List3 <- runif(10)
List2 <- lapply(List2, function(x) unlist(strsplit(x, split = ",")))
List1 <- lapply(List1, function(x) unlist(strsplit(x, split = ",")))
FinalScoreList <- lapply(List1, function(x) {
indicator <- sapply(List2, function(y) {x %in% y})
sum(List3[indicator])
})
unlist(FinalScoreList)
[1] 1.595639 NA NA
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.