【问题标题】:Merging vectors of strings in a list in R在R中的列表中合并字符串向量
【发布时间】:2014-06-16 18:19:45
【问题描述】:

我有一组字符串以及 ID:string 格式的相应 ID 作为 R 中的向量列表

d <- list( c("SD1:LUSH", "SD44:CANCEL", "SD384:FR563", "SD32:TRUMPET"), c("SD23:SWITCH", "SD1:LUSH", "SD567:TREK"), c("SD42:CRAYON", "SD345:FOX", "SD183:WIRE"), c("SD345:HOLE", "SD340:DUST", "SD387:ROLL"), c("SD455:TOMATO", "SD39:MATURE"), c("SD12:PAINTING", "SD315:MONEY31", "SD387:SPRING"),  c("SD32:TRUMPET", "SD1:FIELD"))

[[1]]
[1] "SD1:LUSH"     "SD44:CANCEL"  "SD384:FR563"  "SD32:TRUMPET"

[[2]]
[2] "SD23:SWITCH" "SD1:LUSH"    "SD567:TREK" 

[[3]]
[3] "SD42:CRAYON" "SD345:FOX"   "SD183:WIRE" 

[[4]]
[4] "SD345:HOLE" "SD340:DUST" "SD387:ROLL"

[[5]]
[5] "SD455:TOMATO" "SD39:MATURE" 

[[6]]
[6] "SD12:PAINTING" "SD315:MONEY31"    "SD387:SPRING" 

[[7]]
[7] "SD32:TRUMPET" "SD1:FIELD" 

我想通过它们的 ID 合并向量。需要合并具有公共 ID 的向量,同时保留其对应的字符串以形成新向量。可以在此类合并字符串中删除重复的 ID:字符串组合。总数据包含大约 2000 个这样的向量。样本数据的期望输出是

out <- c("SD1:LUSH, SD1:FIELD,  SD23:SWITCH, SD32:TRUMPET, SD44:CANCEL, SD384:FR563,  SD567:TREK", "SD12:PAINTING, SD42:CRAYON, SD183:WIRE, SD340:DUST SD345:FOX, SD345:HOLE, SD387:SPRING, SD387:ROLL", "SD455:TOMATO, SD39:MATURE") 

[1] "SD1:LUSH, SD1:FIELD,  SD23:SWITCH, SD32:TRUMPET, SD44:CANCEL, SD384:FR563,  SD567:TREK"            
[2] "SD12:PAINTING, SD42:CRAYON, SD183:WIRE, SD315:MONEY31, SD340:DUST SD345:FOX, SD345:HOLE, SD387:SPRING, SD387:ROLL"
[3] "SD455:TOMATO, SD39:MATURE"

我尝试将其转换为data.frame 以使用merge(),但发现它没有用。是否可以先使用字符串的 ID 部分然后搜索相应向量的并集来搜索交集。我曾尝试使用intersect() 和union(),但我未能仅使用向量的 ID 部分。

我对编写 R 脚本相当陌生。

更新 正如@CarlWitthoft 指出的那样,我正在尝试使与此图像合并的匹配条件更加清晰。

简而言之,我想根据 SDxyz:___ 合并它们之间有交集的向量,或者尝试获得重叠字符串向量的并集。

解决了!!

【问题讨论】:

  • 您可以使用lapply(d, strsplit, ":") 拆分ID 部分-但是为什么SD1 和SD23 在out 的第一个元素中,而SD12 在第二个元素中,从我的数据的任何属性都不清楚可以辨别。
  • 向量 1、2 abd 7 应该合并在一起,因为它们之间有共同的 SD1。向量 3、4 和 6 应该合并,因为 SD345 在 3 和 4 之间是常见的,而 SD387 在 4 和 5 之间是常见的。
  • 所以你想要SDxyz中的数字定义的所有可能的合并?您的“所需输出”似乎与您对“匹配条件”的任何文本描述都不匹配
  • @CarlWitthoft 我想合并它们之间至少有一个共同 ID 元素的所有向量。向量 [1]、[2] 和 [7] 之间具有共同的 SD1:___。所以他们应该合并在一起。向量 [4] 具有与向量 [3] 相同的 SD345:___ 和与向量 [5] 相同的 SD387:___。所以向量 [4]、[3] 和 [5] 应该合并在一起。向量 [7] 没有任何与其他向量相同的元素,因此它应该保持原样。有时,同一个 ID 可能与多个字符串相关联,例如 SD1:LUSH 和 SD1:FIELD。
  • @CarlWitthoft 向量 [1]、[2] 和 [7] 之间有 SD1:___ 共同点。向量 [1] 和 [7] 也具有 SD1:___ 和 SD32___ 共同点。所以 [1]、[2] 和 [7] 应该合并在一起。

标签: string r list merge match


【解决方案1】:

创建一个data.table Bloc,其中一列具有原始组,另一列具有分隔的ID

d <- list( c("SD1:LUSH", "SD44:CANCEL", "SD384:FR563", "SD32:TRUMPET"), c("SD23:SWITCH", "SD1:LUSH", "SD567:TREK"), c("SD42:CRAYON", "SD345:FOX", "SD183:WIRE"), c("SD345:HOLE", "SD340:DUST", "SD387:ROLL"), c("SD455:TOMATO", "SD39:MATURE"), c("SD12:PAINTING", "SD315:MONEY31", "SD387:SPRING"),  c("SD32:TRUMPET", "SD1:FIELD"))
d2 <-  lapply(d, function(x) sapply(strsplit(x, ":"), "[", 1))

d <- lapply(d, paste0, collapse=", ")
d2 <- lapply(d2, paste0, collapse=", ")

d <- as.data.frame(as.matrix(lapply(d, paste0, collapse=", ")))
d2 <- as.data.frame(as.matrix(lapply(d2, paste0, collapse=", ")))

d <- as.data.frame(cbind(d,d2))
colnames(d) <- c("sdw", "sd")
d$sd <- as.character(d$sd)
d$sdw <- as.character(d$sdw)

require(data.table)

Bloc <- data.table( d , key = "sd" )

获取所有 id 以及 Bloc 中的相应数据

Bloc <- Bloc[ , list( ID = unlist( strsplit( sd , "," ) ) ) , by = list(sdw, sd) ]
Bloc$ID <- gsub("^\\s+|\\s+$", "", Bloc$ID)
Bloc <- data.table( Bloc , key = "ID" )

循环合并 id 相交的向量

Bloc <- as.data.frame(Bloc)
M <- nrow(Bloc)
#create blankd data.frame
G <- data.frame(matrix(ncol=3), stringsAsFactors=FALSE)
G[,1:3] <- as.character(G[,1:3])
#G <- data.frame(sdw=character(), sd=character(), ID= character())
colnames(G) <- c("sdw", "sd", "ID")
N <- M
mch <- as.data.frame(Bloc)
#Loop to sequentially fill data.frame
for (i in 1:M) {
  # test if ID already in previous groups
  if(Bloc[i,"ID"] %in% G$ID == FALSE) { 
    # convert element to vector to check for intersect
    tm <- strsplit(x=Bloc[i, "sd"], split=", ")
    mch$t <- numeric(length=M)
  }
  for (j in 1:N){
    #if intersect exists apply code as 1 mch$t column
    ff <- strsplit(x=mch[j, "sd"], split=", ")[[1]]
    dd <- intersect (tm[[1]], ff)
    if (identical(dd, character(0))== FALSE) mch[j,"t"] = 1
  }
  submch <- subset(mch, t == 1 )
  ID <- submch$ID
  Group1 <- sort((unlist(strsplit(paste0(submch$sdw, collapse=","), ","))))
  Group1 <- unique(gsub(" ","", Group1))
  sdw <- rep(paste0(Group1, collapse=", "), nrow(submch))
  Group2 <- sort((unlist(strsplit(paste0(submch$sd, collapse=","), ","))))
  Group2 <- unique(gsub(" ","", Group2))
  sd <- rep(paste0(Group2, collapse=", "), nrow(submch))
  G1 <- cbind(sdw, sd, ID)
  G1 <- unique(G1)
  G <- rbind(G, G1)
  mch$t <- NULL
}

G <- unique(G)
G2 <- data.table(G, key="ID")
G2 <- G2[, list(sdw = paste0(sort(unique(unlist(strsplit(sdw, split=", ")))), collapse=", "), 
                sd = paste0(sort(unique(unlist(strsplit(sd, split=", ")))), collapse=", "))  , by = "ID"]
G2 <- data.table( G2, key=c("sd", "sdw"))
G2 <- unique(G2)

获取输出为 data.table

Bloc <- G2[-1,]
Bloc$ID <- NULL

重复上述循环,直到不再有相交点

repeat
{
  N1 <- nrow(Bloc)
  Bloc <- Bloc[ , list( ID = unlist( strsplit( sd , "," ) ) ) , by = list(sdw, sd) ]
  Bloc$ID <- gsub("^\\s+|\\s+$", "", Bloc$ID)
  Bloc <- data.table( Bloc , key = "ID" )

  Bloc <- as.data.frame(Bloc)
  M <- nrow(Bloc)
  #create blankd data.frame
  G <- data.frame(matrix(ncol=3), stringsAsFactors=FALSE)
  G[,1:3] <- as.character(G[,1:3])
  #G <- data.frame(sdw=character(), sd=character(), ID= character())
  colnames(G) <- c("sdw", "sd", "ID")
  N <- M
  mch <- as.data.frame(Bloc)
  #Loop to sequentially fill data.frame
  for (i in 1:M) {
    # test if ID already in previous groups
    if(Bloc[i,"ID"] %in% G$ID == FALSE) { 
      # convert element to vector to check for intersect
      tm <- strsplit(x=Bloc[i, "sd"], split=", ")

      mch$t <- numeric(length=M)
    }
    for (j in 1:N){
      #check if intersect exists and code accordingly
      ff <- strsplit(x=mch[j, "sd"], split=", ")[[1]]
      dd <- intersect (tm[[1]], ff)
      if (identical(dd, character(0))== FALSE) mch[j,"t"] = 1
    }
    submch <- subset(mch, t == 1 )
    ID <- submch$ID
    Group1 <- sort((unlist(strsplit(paste0(submch$sdw, collapse=","), ","))))
    Group1 <- unique(gsub(" ","", Group1))
    sdw <- rep(paste0(Group1, collapse=", "), nrow(submch))
    Group2 <- sort((unlist(strsplit(paste0(submch$sd, collapse=","), ","))))
    Group2 <- unique(gsub(" ","", Group2))
    sd <- rep(paste0(Group2, collapse=", "), nrow(submch))
    G1 <- cbind(sdw, sd, ID)
    G1 <- unique(G1)
    G <- rbind(G, G1)
    mch$t <- NULL
  }

  G <- unique(G)
  G2 <- data.table(G, key="ID")

  G2 <- G2[, list(sdw = paste0(sort(unique(unlist(strsplit(sdw, split=", ")))), collapse=", "), 
                  sd = paste0(sort(unique(unlist(strsplit(sd, split=", ")))), collapse=", "))  , by = "ID"]
  G2 <- data.table( G2, key=c("sd", "sdw"))
  G2 <- unique(G2)
  Bloc <- G2[-1,]
  Bloc$ID <- NULL
  N2 <- nrow(Bloc)  
if (N1 == N2)
break
}

输出

块$sdw

[1] "SD1:FIELD, SD1:LUSH, SD23:SWITCH, SD32:TRUMPET, SD384:FR563, SD44:CANCEL, SD567:TREK"                              
[2] "SD12:PAINTING, SD183:WIRE, SD315:MONEY31, SD340:DUST, SD345:FOX, SD345:HOLE, SD387:ROLL, SD387:SPRING, SD42:CRAYON"
[3] "SD39:MATURE, SD455:TOMATO"  

【讨论】:

    【解决方案2】:

    您可以尝试以下方式:

    id <- lapply(d, function(x) sapply(strsplit(x, ":"), "[", 1))
    tbl <- table(unlist(id))
    

    分离出 ID,并找出哪些 ID 出现在多个条目中:

    repeatIDs <- names(tbl)[tbl>1]
    out <- list()
    

    现在,建立一个包含重复 ID 的压缩列表:

    for (i in repeatIDs) {
        ind <- sapply(id, function(x) any(i==x))
        out[[i]] <- paste(unlist(d[ind]), collapse=", ")
    }
    

    【讨论】:

    • 这是根据 SD1、SD32、SD345 和 SD387 合并样本数据,因为它们在多个向量中重复。我想合并它们之间有交集的向量。我将尝试使用创建的 tbl 表来做同样的事情。
    【解决方案3】:

    我想如果你计算加文答案中的 id ,然后计算所有的 intersect(id[[j]],id[[k]]) ,或者甚至更好:

    for (j in unique(unlist(id))) sapply(id,function(k) j%in%k)
    

    将为您提供交叉点(您必须按摩由该代码产生的 TRUE TRUE FALSE... 向量)

    编辑:所以这是后续操作:

    id <- lapply(sdin, function(x) sapply(strsplit(x, ":"), "[", 1))
    # id is 
    # [[1]]
    # [1] "SD1"   "SD44"  "SD384" "SD32" 
    
    # [[2]]
    # [1] "SD23"  "SD1"   "SD567"
    
    # [[3]]
    # [1] "SD42"  "SD345" "SD183"
    
    # [[4]]
    # [1] "SD345" "SD340" "SD387"
    
    # [[5]]
    # [1] "SD455" "SD39" 
    
    # [[6]]
    # [1] "SD12"  "SD315" "SD387"
    
    # [[7]]
    # [1] "SD32" "SD1"
    
    idnames<-unique(unlist(id)) 
    # [1] "SD1"   "SD44"  "SD384" "SD32"  "SD23"  "SD567" "SD42" 
     # [8] "SD345" "SD183" "SD340" "SD387" "SD455" "SD39"  "SD12" 
    # [15] "SD315"
    
    matid<-matrix(NA,nrow=15,ncol=7)
    for(k in 1:length(idnames) ) matid[k,] <- unlist(sapply(id, function(j) idnames[k]%in%j))
          # [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]
     # [1,]  TRUE  TRUE FALSE FALSE FALSE FALSE  TRUE
     # [2,]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
     # [3,]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
     # [4,]  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE
     # [5,] FALSE  TRUE FALSE FALSE FALSE FALSE FALSE
     # [6,] FALSE  TRUE FALSE FALSE FALSE FALSE FALSE
     # [7,] FALSE FALSE  TRUE FALSE FALSE FALSE FALSE
     # [8,] FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE
     # [9,] FALSE FALSE  TRUE FALSE FALSE FALSE FALSE
    # [10,] FALSE FALSE FALSE  TRUE FALSE FALSE FALSE
    # [11,] FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE
    # [12,] FALSE FALSE FALSE FALSE  TRUE FALSE FALSE
    # [13,] FALSE FALSE FALSE FALSE  TRUE FALSE FALSE
    # [14,] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
    # [15,] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
    

    该矩阵的每一行对应于“SDx”值之一,每一列对应于输入d 列表中的一个列表元素。您应该能够从该表生成您的维恩图。

    【讨论】:

    • 能否详细说明。我无法通过在: 处拆分来创建id 列表。
    猜你喜欢
    • 2018-12-08
    • 1970-01-01
    • 2017-02-19
    • 1970-01-01
    • 2019-04-25
    • 1970-01-01
    • 2012-09-05
    • 2022-01-21
    • 2017-12-07
    相关资源
    最近更新 更多