首页 > 解决方案 > 将数据框中的值与其他列中的其他出现匹配

问题描述

我有一个如下所示的数据框:

df <- data.frame(a = c('x', 'y', 'z', 't', 'm'), b = c('x', 'x', 'y', NA, 'm'))

> df
  a    b
1 x    x
2 y    x
3 z    y
4 t <NA>
5 m    m

现在,对于“a”和“b”列中的每个值,我想看看它是否存在于“a”和“b”的任何其他行中并返回一个匹配项。因此,对于第 1 行,我想查看“x”或“y”是否存在于第 2:5 行的 a 或 b 列中,然后返回“TRUE”。

我想要的结果是:

> df$match = c(TRUE, TRUE, TRUE, FALSE, FALSE)
> df
  a    b match
1 x    x  TRUE
2 y    x  TRUE
3 z    y  TRUE
4 t <NA> FALSE
5 m    m FALSE

似乎无法找到一种方法来做到这一点。我一直在尝试使用 dplyr:

df %>%
  mutate(match = a %in% b | a %in% a | b %in% b | b %in% a)

但这只是将所有内容返回为 TRUE。此外,如果 b 是 NA,那么它也将匹配任何其他非预期的 NA 值。

使用按行操作也不起作用,这只是检查行内的值。

标签: rdplyr

解决方案


这是使用以下tidyverse方法解决您的问题的方法purrr::imap

  • 因为我使用公式快捷方式来定义我的函数.x参数是指值,而.y参数是指位置/名称
  • 我首先转置您的数据集(认为这样可能更容易)然后遍历每一列并检查是否可以在其他列中找到任何元素
  • 为了检查值的存在,我使用.y参数从原始数据集中删除每一列的相应索引,例如转置数据集中的第一列元素与原始数据第一行中的值完全相同数据集
library(dplyr)
library(purrr)

df %>%
  t() %>%
  as_tibble(.name_repair = "unique") %>%
  imap_lgl(~ any(unlist(.x) %in% unlist(df[-as.integer(gsub("\\.{3}(\\d)", "\\1", .y)), ]))) %>%
  unlist() -> df$match

  a    b match
1 x    x  TRUE
2 y    x  TRUE
3 z    y  TRUE
4 t <NA> FALSE
5 m    m FALSE

推荐阅读