【问题标题】:How to check whether all values in grouped columns are the same?如何检查分组列中的所有值是否相同?
【发布时间】:2022-10-07 15:57:47
【问题描述】:

如何检查分组列中的所有值是否相同?

例如,我有以下df:

   id category yes
1   1       in   1
2   1       in   1
3   1       in   1
4   1       in   1
5   1       in   1
6   1      out   1
7   1      out   1
8   1      out   1
9   2       in   1
10  2       in   1
11  2      out   0
12  2      out   1
13  2      out   1
14  3       in   1
15  3       in   1
16  3       in   0
17  3      out   1
18  3      out   1
19  4       in   1
20  4       in   1
21  4       in   1
22  4      out   1
23  4      out   0

我想做这样的事情:

df <- df %>%
  group_by(id, category) %>%
  mutate(
    out = ifelse(# id, category, and yes have the same values in each row within the group)
  )

所以预期的输出将如下所示:

   id category yes same
1   1       in   1    1
2   1       in   1    1
3   1       in   1    1
4   1       in   1    1
5   1       in   1    1
6   1      out   1    1
7   1      out   1    1
8   1      out   1    1
9   2       in   1    1
10  2       in   1    1
11  2      out   0    0
12  2      out   1    0
13  2      out   1    0
14  3       in   1    0
15  3       in   1    0
16  3       in   0    0
17  3      out   1    1
18  3      out   1    1
19  4       in   1    1
20  4       in   1    1
21  4       in   1    1
22  4      out   1    0
23  4      out   0    0

第 11-13 行具有相同的“id”和“category”,但“yes”列具有不同的值。因此,“相同”列应标记为 0(因为它们不相同)。与第 14-16 行和第 22-23 行相同。

这是df的可重现代码:

structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L), category = c("in", 
"in", "in", "in", "in", "out", "out", "out", "in", "in", "out", 
"out", "out", "in", "in", "in", "out", "out", "in", "in", "in", 
"out", "out"), yes = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
0L, 1L, 1L, 1L, 1L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 0L)), class = "data.frame", row.names = c(NA, -23L))

任何指导将不胜感激!

【问题讨论】:

    标签: r dplyr group-by


    【解决方案1】:

    我们可以使用n_distinct 来检查组中唯一元素的频率,转换为逻辑(== 1),然后使用as.integer+ 转换为二进制

    library(dplyr)
    df %>%
      group_by(id, category) %>% 
      mutate(same = +(n_distinct(yes) == 1)) %>% 
      ungroup
    

    或使用data.table

    library(data.table)
    setDT(df)[, same := +(uniqueN(yes) == 1), by = .(id, category)]
    

    【讨论】:

    • 我尝试了这个解决方案,但它需要很长时间才能运行。 (已经10分钟了。)这正常吗?
    • @hy9fesh 你的数据集有多大?和多少组
    • 将近一百万行。不过,我已经能够毫无问题地运行其他 dplyr 命令。
    • 那应该很快。您也可以尝试使用data.table,即library(data.table); setDT(df)[, out := +(all(yes)), by = .(id, category)]
    • @hy9fesh 我想当每组只有 0 个值时这可能是一个问题。尝试更新版本的代码
    【解决方案2】:

    如果您的数据是 data.table,则一种选择。

    我不认为在像这个例子这样你只有一列要检查的情况下,这不是一个好的解决方案。在这种情况下,您可以像 @akrun 节目一样使用 uniqueN。如果我没记错的话,当你在下面的函数的cols 参数中有很多行和很多列时,这会更快,因为在这种情况下使用uniqueN 你必须首先创建一个data.table from您要检查的列,每组一次(uniqueN 输入必须是向量或 data.table)。但是,我没有任何基准,所以也许我记错了。

    library(data.table)
    setDT(df)
    
    check_single_value <- function(df, col_uq, by, show_groups = FALSE) {
      n_uq <- unique(df[, c(col_uq, by), with = FALSE])[, .N, by = by]
      if (show_groups)
        n_uq[N > 1]
      else 
        n_uq[, !any(N > 1)]
    }
    
    check_single_value(df, 'yes', by = c('id', 'category'))
    #> [1] FALSE
    
    check_single_value(df, 'yes', by = c('id', 'category'), show_groups = T)
    #>       id category     N
    #>    <int>   <char> <int>
    #> 1:     2      out     2
    #> 2:     3       in     2
    #> 3:     4      out     2
    

    reprex package (v2.0.1) 于 2022 年 2 月 24 日创建

    【讨论】:

      【解决方案3】:

      我想我有一个更简单的解决方案。

      df &lt;- df %&gt;% group_by(id, category) %&gt;% mutate(n_unique = length(unique(yes)))

      该代码将为您提供 id-category 组中 yes 的唯一值的数量。您可以使用此操作以获得所需的结果。

      【讨论】:

        猜你喜欢
        • 2021-09-11
        • 2012-05-20
        • 2021-03-20
        • 1970-01-01
        • 1970-01-01
        • 2013-01-29
        • 1970-01-01
        • 2019-06-21
        • 1970-01-01
        相关资源
        最近更新 更多