包含许多行的表,但为了简化问题...
> 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
注意:搜索必须向上。
答案 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