将多列进行比较以相等

Comparing multiple columns to equality

提问人:an_drade 提问时间:5/10/2022 更新时间:5/12/2022 访问量:1082

问:

这可能是使用 dplyrtidyverse 工具的一个非常基本的问题,但我不能 找到一个好方法。

假设我有一个宽格式的数据框,并且我想选择行,以便列的子集具有相同的值。天真地,我可以做到以下几点:

> df <- tribble(
    ~name, ~id,  ~cost, ~value1 , ~value2, ~value3,
    "a",     1,     10,       1,        1,       1,
    "a",     2,     20,       1,        2,       1,
    "b",     3,     50,       1,        1,       3,
    "b",     4,     45,       1,        1,       1,
    "b",     5,     70,       2,        2,       2
)


> df %>% select(
    value1 == value2 &
    value1 == value3 &
    value2 == value
)

# A tibble: 3 × 6
  name     id  cost value1 value2 value3
  <chr> <dbl> <dbl>  <dbl>  <dbl>  <dbl>
1 a         1    10      1      1      1
2 b         4    45      1      1      1
3 b         5    70      2      2      2

现在,让我们假设要比较的列数非常大(> 10)。所有列都以 开头,因此我们可以有 ,即不一定是本例中的数字。但是,如果列数是 ,我天真地必须进行比较,这显然是无法管理的。valuevalue_something, value_otherthing, value_morethingnn * (n - 1) / 2

有没有类似的东西

df %>% filter(all_same(starts_with("value")))

其中按 starts_with()(或任何其他选择器)比较所有选定的列?all_same()

rowwise() 和 across() 也没有对我有太大帮助。

R 筛选器 tidyverse 相等开始

评论


答:

5赞 akrun 5/10/2022 #1

我们可以用来遍历从 'value2' 到 'value3' 的列,检查列值是否等于 ,仅对所有列比较均为 TRUE 的行返回 TRUEif_allvalue1if_all

library(dplyr)
df %>%
    filter(if_all(value2:value3, ~ value1 == .x))

-输出

# A tibble: 3 × 6
  name     id  cost value1 value2 value3
  <chr> <dbl> <dbl>  <dbl>  <dbl>  <dbl>
1 a         1    10      1      1      1
2 b         4    45      1      1      1
3 b         5    70      2      2      2

或者,如果我们想使用starts_with

df %>%
    filter(if_all(starts_with('value'), ~ value1 == .x))

评论

1赞 an_drade 5/11/2022
谢谢@akrun!这是一个很好而清晰的解决方案。
1赞 AndrewGB 5/11/2022 #2

这是一个可能的基本 R 选项,我们可以计算唯一值的数量,以查看每行是否只有 1 个(并且仅适用于“值”列)。

df[apply(df[, -c(1:3)], 1, function(x) length(unique(x)) == 1), ]

或者另一种选择是用于选择以“value”(而不是索引)开头的列。startsWith

df[apply(df[, startsWith(names(df), "value")], 1, function(x)
  length(unique(x)) == 1),]

输出

  name     id  cost value1 value2 value3
  <chr> <dbl> <dbl>  <dbl>  <dbl>  <dbl>
1 a         1    10      1      1      1
2 b         4    45      1      1      1
3 b         5    70      2      2      2

评论

1赞 an_drade 5/12/2022
谢谢@AndrewGB。如果您确切地知道列的位置,这是一个不错的选择。
0赞 AndrewGB 5/12/2022
@an_drade没问题!但是,我们也可以使用基础 R 来选择列,而不是使用索引。我也将该选项添加到我的答案中。startsWith