dplyr использует как строчные, так и df-значения в мутировании
Как вы выполняете rowwise
операция, которая использует значения из других строк (в стиле dplyr/tidy)? Допустим, у меня есть этот df:
df <- data_frame(value = c(5,6,7,3,4),
group = c(1,2,2,3,3),
group.to.use = c(2,3,3,1,1))
Я хочу создать новую переменную, new.value, которая равна текущему значению каждой строки плюс максимальное значение для строк, чья "группа" равна "group.to.use" этой строки. Так для первого ряда
new.value = 5 + (max(value[group === 2])) = 5 + 7 = 12
желаемый результат:
# A tibble: 5 x 4
value group group.to.use new.value
<dbl> <dbl> <dbl> <dbl>
1 5. 1. 2. 12.
2 6. 2. 3. 10.
3 7. 2. 3. 11.
4 3. 3. 1. 8.
5 4. 3. 1. 9.
псевдокод:
df %<>%
mutate(new.value = value + max(value[group.to.use == <group.for.this.row>]))
3 ответа
В режиме строки вы можете ссылаться на весь data.frame с помощью .
и целый столбец в data.frame с нормальным синтаксисом .$colname
или же .[['col.name']]
:
df %>%
rowwise() %>%
mutate(new.value = value + max(.$value[.$group == group.to.use])) %>%
ungroup()
# # A tibble: 5 x 4
# value group group.to.use new.value
# <dbl> <dbl> <dbl> <dbl>
# 1 5 1 2 12
# 2 6 2 3 10
# 3 7 2 3 11
# 4 3 3 1 8
# 5 4 3 1 9
Кроме того, вы можете предварительно вычислить максимум для каждой группы, а затем выполнить левое соединение:
df.max <- df %>% group_by(group) %>% summarise(max.value = max(value))
df %>%
left_join(df.max, by = c('group.to.use' = 'group')) %>%
mutate(new.value = value + max.value) %>%
select(-max.value)
# # A tibble: 5 x 4
# value group group.to.use new.value
# <dbl> <dbl> <dbl> <dbl>
# 1 5 1 2 12
# 2 6 2 3 10
# 3 7 2 3 11
# 4 3 3 1 8
# 5 4 3 1 9
С базой R мы можем использовать ave
где мы рассчитываем max
для каждого group
и добавить их с соответствующими value
match
группы.
df$new.value <- with(df, value +
ave(value, group, FUN = max)[match(group.to.use, group)])
df
# A tibble: 5 x 4
# value group group.to.use new.value
# <dbl> <dbl> <dbl> <dbl>
#1 5.00 1.00 2.00 12.0
#2 6.00 2.00 3.00 10.0
#3 7.00 2.00 3.00 11.0
#4 3.00 3.00 1.00 8.00
#5 4.00 3.00 1.00 9.00
Вот вариант с base R
df$new.value <- with(df, value + vapply(group.to.use, function(x)
max(value[group == x]), numeric(1)))
df$new.value
#[1] 12 10 11 8 9