将为一组计算的平均值分配给另一组的行

时间:2019-06-15 23:37:27

标签: r join dplyr

我有以下问题: 我有这样的数据:

tribble(~label_a, ~label_b, ~value,
    "a", "x", 1,
    "a", "x", 3,
    "a", "y", 6,
    "a", "y", 8,
    "b", "x", 10,
    "b", "x", 30,
    "b", "y", 60,
    "b", "y", 80,
    )

我想(使用Dplyr)将其按label_a分组,然后按label_b分组,计算平均值,但仅对于label_b等于“ x”的组,将这个平均值用于label_a组中的所有行作为新列获得这样的东西:

label_a | label_b | value | x_mean
----------------------------------
a       | x       | 1     | 2
a       | x       | 3     | 2
a       | y       | 6     | 2
a       | y       | 8     | 2
b       | x       | 10    | 20
b       | x       | 30    | 20
b       | y       | 60    | 20
b       | y       | 80    | 20

但是我不知道该怎么做。预先感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

我看到了两种方法:一种简单的方法,如果您拥有标签或将获得更多级别的标签,这将变得更加困难,而另一种方法则需要更多的代码,但可能对更大的数据更健壮。

1:容易,但扩展性很差

x %>%
  group_by(label_a) %>%
  mutate(x_mean = mean(if_else(label_b == "x", value, value[NA]), na.rm = TRUE)) %>%
  ungroup()
# # A tibble: 8 x 4
#   label_a label_b value x_mean
#   <chr>   <chr>   <dbl>  <dbl>
# 1 a       x           1      2
# 2 a       x           3      2
# 3 a       y           6      2
# 4 a       y           8      2
# 5 b       x          10     20
# 6 b       x          30     20
# 7 b       y          60     20
# 8 b       y          80     20

这个问题的症结在于,我们仅取"x"值的平均值,而忽略其余的值。 if_else的使用给出了矢量化的if / then-like语句,而value[NA]的使用是为了保证我们得到“正确的NA类型”(除了R中有几个不同的NA

2:更强大

x %>%
  filter(label_b == "x") %>%
  group_by(label_a) %>%
  summarize(x_mean = mean(value)) %>%
  left_join(x, ., by = "label_a") %>%
  ungroup()
# # A tibble: 8 x 4
#   label_a label_b value x_mean
#   <chr>   <chr>   <dbl>  <dbl>
# 1 a       x           1      2
# 2 a       x           3      2
# 3 a       y           6      2
# 4 a       y           8      2
# 5 b       x          10     20
# 6 b       x          30     20
# 7 b       y          60     20
# 8 b       y          80     20

首先创建一个摘要表,该方法就可以使用

x %>%
  filter(label_b == "x") %>%
  group_by(label_a) %>%
  summarize(x_mean = mean(value))
# # A tibble: 2 x 2
#   label_a x_mean
#   <chr>    <dbl>
# 1 a            2
# 2 b           20

然后合并回到原始框架。在基数R中,我们将使用merge,在SQL中,并且使用dplyr来说,我们将使用join运算符。 (这里有多个类似多个联接操作的示例:How to join (merge) data frames (inner, outer, left, right),我鼓励您看一下并尝试一些示例以了解发生了什么。)

将中间摘要表存储在另一个变量中并与原始框架一起join放在另一个管道中并不少见。在这种情况下,我只是做了一个类似“ self-join”的事情(尽管到加入连接操作时,它离“ selfself”还很远)。

答案 1 :(得分:0)

万一有人寻找data.table解决方案:

dt[, x_mean := mean(value[label_b == 'x'])
   , by = label_a]