How do you perform a rowwise
operation which uses values from other rows (in dplyr/tidy style)? Let's say I have this 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))
I want to create a new variable, new.value, which is equal to each row's current value plus the maximum of value for rows whose "group" equals this row's "group.to.use." So for the first row
new.value = 5 + (max(value[group === 2])) = 5 + 7 = 12
desired output:
# 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.
pseudo code:
df %<>%
mutate(new.value = value + max(value[group.to.use == <group.for.this.row>]))
In rowwise operation, you can refer to the whole data.frame with .
and a whole column in the data.frame with normal syntax .$colname
or .[['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
Alternatively, you can precompute the max for each group and then do a left-join:
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
With base R, we can use ave
, where we calculate max
for each group
and add them with the corresponding value
match
ing the groups.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With