我有以下问题: 我有这样的数据:
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
但是我不知道该怎么做。预先感谢您的帮助。
答案 0 :(得分:2)
我看到了两种方法:一种简单的方法,如果您拥有标签或将获得更多级别的标签,这将变得更加困难,而另一种方法则需要更多的代码,但可能对更大的数据更健壮。
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
。
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]