【问题标题】:r - for loop to compare 2 dataframes all by all rowsr - for 循环按所有行比较 2 个数据帧
【发布时间】:2021-09-16 10:45:12
【问题描述】:

我正在尝试逐行比较数据框 d1 中的 2 列与数据框 d2 中的 2 列。为了说明我创建虚拟数据集的问题:

d1 <- data.frame(
  a = c(1,2,3),
  b = c(4,5,6)
)

d2 <- data.frame(
  a = c(2,0,2),
  b = c(5,5,6)
)

理想情况下,我想标记d1 中的所有行,我可以在d2 的至少一行中找到匹配项,所以想要的结果是:

data.frame(
  a = c(1,2,3),
  b = c(4,5,6),
  flag = c(0,1,0)
)

这是我尝试过的:

for (i in 1:nrow(d1)) {
  for (j in 1:nrow(d2)) {
    test[i,j] = ifelse(d1$a[i] == d2$a[j] & d1$b[i] == d2$b[j], 1, 0)
  }
}

for 循环是最好的解决方案

【问题讨论】:

  • 因为 d2 中没有 a=3 和 b=6 的行

标签: r for-loop compare


【解决方案1】:

你基本上是在寻找一种加入。对于这个特殊任务,仅标记,data.table 在这里非常简洁,具有就地连接和更新

library(data.table)
d1 <- data.table(
  a = c(1,2,3),
  b = c(4,5,6)
)

d2 <- data.table(
  a = c(2,0,2),
  b = c(5,5,6)
)


# assign 1 to each match in place
d1[d2,
   on = .(a, b),
   flag := 1]
d1
#>    a b flag
#> 1: 1 4   NA
#> 2: 2 5    1
#> 3: 3 6   NA

# convert NAs to zeros
d1[is.na(flag), flag := 0]
d1
#>    a b flag
#> 1: 1 4    0
#> 2: 2 5    1
#> 3: 3 6    0

【讨论】:

  • 感谢您的回答。由于 data.table 当前未提供的连接的复杂性,我更喜欢 for 循环
  • 什么意思?请提供您的问题的实际示例
  • 我需要使用 stringr::str_detect(d1$a[i], d2$a[j])
  • 请提供您实际问题的实际示例
【解决方案2】:

您可以为此使用match

d1$flag <- match(paste0(d1$a, d1$b), paste0(d2$a, d2$b), nomatch = 0)

编辑:@mnist 提出了一个公平的观点。以下是对 NA 行更安全的替代方法:

d1$flag <- as.numeric(duplicated(rbind(d2, d1)))[-seq_len(nrow(d1))]

【讨论】:

  • 简洁但容易出错,因为paste0("a", "")paste0("", "a") 是等效的。
  • 非常好。我添加了一个可以规避这种情况的替代方案,只是可读性差了一点
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-10
  • 1970-01-01
  • 2017-06-01
  • 1970-01-01
  • 2018-09-27
  • 2021-12-14
  • 1970-01-01
相关资源
最近更新 更多