在超过 n 个数字列中具有重复值的数据帧的平均行

Average rows of dataframe with duplicated values in more than n numerical columns

我希望能够使用 dplyr 对任何 n 或更多数字列中具有相同值且 a 中具有相同值的行进行平均列。

如果:

n <- 3

df <- data.frame(a = c("one", "one", "one", "one", "three"),
                 b = c(1,1,1,2,3),
                 c = c(2,2,2,7,12),
                 d = c(6,6,7,8,10),
                 e = c(1,4,1,3,4))

那么我想取前三行的平均值(因为它们之间4个数值中有3个相同,a中的值也相同)。我不希望第四行包含在平均值中,因为尽管 a 中的值相同,但它没有相同的数值。

之前:

    a      b   c   d   e   
[1] one    1   2   6   1
[2] one    1   2   6   4
[3] one    1   2   7   1
[4] one    2   7   8   3
[5] four   3  12  10   4

之后:

    a      b   c    d   e   
[1] one    1   2   6.3  2
[2] one    2   7    8   3
[3] four   3  12   10   4

我的数据框在现实生活中要大得多,并且包含许多其他列。

编辑: 行 [1][2] 有 3 个相同的值(在列 bcd 中。行 [1][3] 有3 个相同的值(在 bce 列中。这就是为什么我希望它们取平均值。

在这里,我首先按 a 列对数据帧进行分组。然后,对于每个 sub-dataframe,我根据行之间不同元素的数量计算一个距离矩阵。

使用包 proxy 是因为它可以轻松计算自定义距离。

然后,我执行 single-linkage 聚类并在刚好高于 1 的高度切割树。这将确保聚类中的每个成员至少有 (4 - 1) = 3 个元素与至少同一集群的另一个成员。

最后,我通过簇号gid总结了每个sub-dataframe。

library(dplyr)
library(tidyr)
library(proxy)

n <- 3

df <- data.frame(a = c("one", "one", "one", "one", "three"),
                 b = c(1,1,1,2,3),
                 c = c(2,2,2,7,12),
                 d = c(6,6,7,8,10),
                 e = c(1,4,1,3,4))



df |>
  group_by(a) |>
  group_modify(~{
    gid <- if(nrow(.x) > 1)
               proxy::dist(.x, method = \(a,b) sum(a != b)) |>
               hclust(method="single") |>
               cutree(h = 0.1 + ncol(.x) - n)
           else
             1
    group_by(cbind(.x, gid), gid) |>
      summarize(across(everything(), mean))
  })

# A tibble: 3 × 6
# Groups:   a [2]
  a       gid     b     c     d     e
  <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 one       1     1     2  6.33     2
2 one       2     2     7  8        3
3 three     1     3    12 10        4

这是从前 4 行获得的示例树状图: