tidyverse mutate with an external vector whose elements are column values in a data frame

101 Views Asked by At

Let's assume the following vector:

prices <- c(10, 15, 20, 30)

and the following data frame:

df <- data.frame(count = c(1, 3, 2, 4))

What I want to do is, depending on the count value in df, taking the 1:count values from the prices vector and sum these up in my data frame.

So I thought I could do:

library(tidyverse)
df |>
  mutate(sum = sum(!!prices[1:count]))

However, this gives an error:

Error in quos(..., .ignore_empty = "all") : 
  object 'count' not found

I guess it's because it looking into the external vector and then searching for count in the global environment, however, it only exists in df.

So question is how can I feed in this external vector into my data frame an reference its elements by the count values?

Expected output would be:

  count sum
1     1  10
2     3  45
3     2  25
4     4  75
3

There are 3 best solutions below

1
Maël On BEST ANSWER

With sapply. And use .GlobalEnv$ if necessary:

df |>
  mutate(sum = sapply(count, \(x) sum(.GlobalEnv$prices[1:x])))

#   count sum
# 1     1  10
# 2     3  45
# 3     2  25
# 4     4  75
2
langtang On

You can wrap df in rowwise()

library(dplyr)
mutate(rowwise(df), total = sum(prices[1:count]))

Output:

  count total
  <int> <dbl>
1     1    10
2     2    25
3     3    45
4     4    75
2
Ronak Shah On

You may subset prices with help of count and then use cumsum.

library(dplyr)

df %>% mutate(sum = cumsum(prices[count]))

#  count sum
#1     1  10
#2     2  25
#3     3  45
#4     4  75

Based on your comment on other answer if there is a possibility that the dataframe can have a column named prices then this will not work. In such case specify .GlobalEnv to explicitly use prices from global environment.

df <- data.frame(count = 1:4, prices = 4:1)

df %>% mutate(sum = cumsum(.GlobalEnv$prices[count]))