簡體   English   中英

R通過lapply將函數應用於列表

[英]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

因此,輸出中的每一行都指定兩個列表( X1X2 )的組合,並且列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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM