搜索最近的字符串

时间:2017-06-26 17:45:47

标签: r

包含许多行的表,但为了简化问题...

> df <- data.frame(V1=c("imp: abc","apple","","imp: xyz","","lemon","ball","bell"),
                 V2=c("1","2","3","4","5","6","7","8"),
                 V3=c("NA","7","NA","2,8","NA","NA","NA","NA"))

      V1               V2              V3
1  imp: abc             1              NA
2  apple                2              7
3                       3              NA
4  imp: xyz             4              2,8
5                       5              NA
6  lemon                6              NA
7  ball                 7              NA
8  bell                 8              NA

所以我想要实现的是在V1中基于V3和V2搜索最近的字符串“imp:”。例如,V3是7,然后转到第7行并从那里搜索V1中最近的“imp:”,这只是imp:xyz存在于第4行。

如果V3中有多个数字,例如V3是2,那么首先进入第2行,然后从那里搜索V1中最近的“imp:”,这只是imp:abc存在于第1行并再次出现转到第8行并从那里搜索V1中最近的“imp:”,这只是imp:xyz出现在第4行。

以下是输出结果:

      V1               V2              V3          V4
1  imp: abc             1              NA
2  apple                2              7           imp: xyz 
3                       3              NA
4  imp: xyz             4              2,8         imp: abc, imp: xyz
5                       5              NA
6  lemon                6              NA
7  ball                 7              NA
8  bell                 8              NA

注意:搜索必须向上。

1 个答案:

答案 0 :(得分:1)

这是一个解决方案,虽然它不是那么快 - 如果你有很多行,它可能不是最好的方法。使用上述df,首先确保您的NA值不是字符串,然后添加一个填充NA的列V4:

df$V3[df$V3 == "NA"] <- NA
df$V4 <- NA

将V3中的索引值解析为单个数值:

keys <- strsplit(as.character(df$V3), ",")

keysn <- lapply(keysn, as.numeric)

编辑:忘记这两行,将原始df中的rownames分配给列表列表。添加这些,它应该工作 - 如果没有,请再次告诉我!

names(keysn) <- rownames(df)

keysn <- keysn[!is.na(keysn)]

然后,使用lapply迭代数字索引列表列表,并将第1行的最大行数的V1值提取到当前索引。对于多值(例如,2,8),请在返回之前将这些值粘贴在一起。

lx<-lapply(keysn, function(x){
  xout <-lapply(x, function(y){
    rn <- unlist(as.numeric(row.names(df[1:y,])))
    matchvals <- rn[which(grepl("imp", as.character(df$V1)))]
    matchvals <- matchvals[which(!is.na(matchvals))]
    maxmatch <- max(matchvals)
    out_text <- as.character(df$V1[maxmatch])
  })
  xout <- paste(xout, collapse = ", ")
  return(unlist(as.character(xout)))
})

> lx
$`2`
[1] "imp: xyz"

$`4`
[1] "imp: abc, imp: xyz"

最后,使用列表项的名称来使用适当的值更新V4列。

df$V4[as.numeric(names(lx))] = lx

> df
        V1 V2   V3                 V4
1 imp: abc  1 <NA>                 NA
2    apple  2    7           imp: xyz
3           3 <NA>                 NA
4 imp: xyz  4  2,8 imp: abc, imp: xyz
5           5 <NA>                 NA
6    lemon  6 <NA>                 NA
7     ball  7 <NA>                 NA
8     bell  8 <NA>                 NA