匹配两列R的相邻列

时间:2019-07-18 08:08:08

标签: r apply

我有一个看起来像这样的数据框:

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函数。

2 个答案:

答案 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))