Bubbles
Bubbles

Reputation: 569

modify/create column based on groups defined externally

I have a predefined list containing a list of items as below:

group_1<-c("A","B","C")
group_2<-c("D","E","F")

item<-c("A","B","C","D","E","F")
item_price<-(1:6)

df<-data.frame(item,item_price)

> df
  item item_price
1    A          1
2    B          2
3    C          3
4    D          4
5    E          5
6    F          6

And now, what I would like to do is to create a new column, multiplying item_price by an arbitrary number, in this case, for items in group_1, item_price will be multiplied by 0.1 and 0.2 for those in group 2. Desired output as below:

> df
  item item_price df_new_rate
1    A          1         0.1
2    B          2         0.2
3    C          3         0.3
4    D          4         0.8
5    E          5         1.0
6    F          6         1.2

Since I will need to loop thru item column and see which group different item belongs to, do I need to write a for loop here? Or if there is a short and clear cut way to do so? All ideas are appreciated.

Upvotes: 2

Views: 64

Answers (4)

zx8754
zx8754

Reputation: 56219

Using a lookup named vector:

lookup <- c(setNames(rep(0.1, length(group_1)), group_1),
            setNames(rep(0.2, length(group_2)), group_2))

df$df_new_rate <- df$item_price * lookup[ df$item ]
#   item item_price df_new_rate
# 1    A          1         0.1
# 2    B          2         0.2
# 3    C          3         0.3
# 4    D          4         0.8
# 5    E          5         1.0
# 6    F          6         1.2

Upvotes: 2

Jon Spring
Jon Spring

Reputation: 66880

If there are potentially many groups, a lookup table might be a good way to maintain:

library(dplyr)
lookup <- data.frame(item = c(group_1, group_2),
                     rt = c(rep(0.1, length(group_1)),
                            rep(0.2, length(group_2))))

df |> left_join(lookup) |> mutate(df_new_rate = item_price * rt)

Result

Joining with `by = join_by(item)`
  item item_price  rt df_new_rate
1    A          1 0.1         0.1
2    B          2 0.1         0.2
3    C          3 0.1         0.3
4    D          4 0.2         0.8
5    E          5 0.2         1.0
6    F          6 0.2         1.2

Upvotes: 0

Michiel Duvekot
Michiel Duvekot

Reputation: 1881

# tidyverse solution
library(dplyr)
df <- df |> mutate(
  new_rate = ifelse(item %in% group_1, item_price*.1, item_price*.2)
  )
df

# same, but in base R
df$new_rate <- ifelse(df$item %in% group_1, df$item_price*.1, df$item_price*.2)
df

Upvotes: 2

M--
M--

Reputation: 29153

You can use ifelse or case_when if you have more than 2 groups:

library(dplyr)

df %>% 
  mutate(df_new_rate = case_when(item %in% group_1 ~ 0.1,
                                 item %in% group_2 ~ 0.2,
                                 .default = 0) * item_price)
#>   item item_price df_new_rate
#> 1    A          1         0.1
#> 2    B          2         0.2
#> 3    C          3         0.3
#> 4    D          4         0.8
#> 5    E          5         1.0
#> 6    F          6         1.2

Upvotes: 4

Related Questions