提问人:an_drade 提问时间:5/10/2022 更新时间:5/12/2022 访问量:1082
将多列进行比较以相等
Comparing multiple columns to equality
问:
这可能是使用 dplyr 和 tidyverse 工具的一个非常基本的问题,但我不能 找到一个好方法。
假设我有一个宽格式的数据框,并且我想选择行,以便列的子集具有相同的值。天真地,我可以做到以下几点:
> 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)。所有列都以 开头,因此我们可以有 ,即不一定是本例中的数字。但是,如果列数是 ,我天真地必须进行比较,这显然是无法管理的。value
value_something, value_otherthing, value_morething
n
n * (n - 1) / 2
有没有类似的东西
df %>% filter(all_same(starts_with("value")))
其中按 starts_with()(
或任何其他选择器)比较所有选定的列?all_same()
答:
5赞
akrun
5/10/2022
#1
我们可以用来遍历从 'value2' 到 'value3' 的列,检查列值是否等于 ,仅对所有列比较均为 TRUE 的行返回 TRUEif_all
value1
if_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
评论