我有一个看起来像这样的数据框:
V1 V2 V3 V4 V5
A C B D NA
B D NA NA NA
D B A E NA
D A C E B
和另一个具有成对的列的数据框,例如:
Col1 Col2
A B
B D
C E
B A
E B
我想使用包含Col1和Col2的配对数据帧在第一个数据帧及其位置中找到这些连续的对。
所以它会导致类似于:
[1] 3 4
[2] 1 2
[3] 2 3
[4] 3 4 5
我尝试过for循环,但是它效率极低并且容易出错。我真的很感谢一些建议,也许有apply函数。
答案 0 :(得分:1)
有两种解决方案,但都不是完美的。以下,df1
是第一个数据帧,df2
是第二个数据帧。
以下解决方案基于以下事实:值是规则的-始终具有相同的格式,并且它们不包含'-'。
df1B <- sapply(1:(ncol(df1) - 1), function(i) paste0(df1[,i], "--", df1[,i+1]))
pat <- paste0(df2[,1], "--", df2[,2])
apply(df1B, 1, function(r) which(r %in% pat))
这将返回一个列表,其中每一行都包含一个元素。鉴于您的第二个数字始终是第一个数字加一个,因此解决方案与您的预期结果相同:
[[1]]
[1] 3
[[2]]
[1] 1
[[3]]
[1] 2
[[4]]
[1] 3 4
请注意,这不是一般的解决方案,因为如果df2的一个单元格包含“ A--B”,则搜索模式将为“ A--B--C”,并且将两者都匹配(“ --B“,” C“)和(” A“,” B--C“)。
将结果列表转换为数据帧格式是可能的,但很麻烦。
res <- apply(df1B, 1, function(r) which(r %in% pat))
max <- max(sapply(res, length))
df <- lapply(1:max, function(i) sapply(res, function(r) c(r[i], r[i] +1)))
df <- Reduce(cbind, lapply(df, t))
结果
> df
[,1] [,2] [,3] [,4]
[1,] 3 4 NA NA
[2,] 1 2 NA NA
[3,] 2 3 NA NA
[4,] 3 4 4 5
答案 1 :(得分:0)
使用逐行apply
的一种方法是创建行元素的组合,并将它们paste
一起创建,检查在df2
的粘贴版本中有多少元素一起出现并返回索引。
apply(df1, 1, function(x) {
inds <- which(paste(x[-length(x)], x[-1]) %in% paste(df2$Col1, df2$Col2))
unique(c(inds, inds + 1))
})
#[[1]]
#[1] 3 4
#[[2]]
#[1] 1 2
#[[3]]
#[1] 2 3
#[[4]]
#[1] 3 4 5
数据
df1 <- structure(list(V1 = structure(c(1L, 2L, 3L, 3L), .Label = c("A",
"B", "D"), class = "factor"), V2 = structure(c(3L, 4L, 2L, 1L
), .Label = c("A", "B", "C", "D"), class = "factor"), V3 = structure(c(2L,
NA, 1L, 3L), .Label = c("A", "B", "C"), class = "factor"), V4 = structure(c(1L,
NA, 2L, 2L), .Label = c("D", "E"), class = "factor"), V5 = structure(c(NA,
NA, NA, 1L), .Label = "B", class = "factor")), class = "data.frame", row.names
= c(NA, -4L))
df2 <- structure(list(Col1 = structure(c(1L, 2L, 3L, 2L, 4L), .Label = c("A",
"B", "C", "E"), class = "factor"), Col2 = structure(c(2L, 3L,
4L, 1L, 2L), .Label = c("A", "B", "D", "E"), class = "factor")), class =
"data.frame", row.names = c(NA, -5L))