Присвоение среднего значения, рассчитанного для одной группы, строкам другой группы - PullRequest
0 голосов
/ 16 июня 2019

У меня следующая проблема: у меня есть такие данные:

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 ]

2 голосов
/ 16 июня 2019

Я вижу два способа сделать это: простой способ, который становится намного сложнее, если у вас есть или вы получите больше уровней с метками, и один, который немного больше кода, но может быть более устойчивым к большим данным.

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» (существует более чем несколько различных NA sв R).

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 -speak мы используем оператор join.(Здесь приведено несколько примеров нескольких операций, подобных соединению: Как объединить (объединить) фреймы данных (внутренний, внешний, левый, правый) , я рекомендую вам взглянуть и попробовать некоторые из примеровчтобы увидеть, что происходит.)

Нередко промежуточную сводную таблицу хранят в другой переменной и редактируют join с исходным кадром в другом канале.В данном случае я просто сделал что-то вроде «self- join» (хотя к моменту перехода к операции соединения оно далеко от «себя»).

0 голосов
/ 16 июня 2019

Если кто-то ищет решение data.table:

dt[, x_mean := mean(value[label_b == 'x'])
   , by = label_a]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...