I have a time series dataframe and would like to create a new numeric column with values which are a function of an existing numeric column and which are assigned according to the day of the week column.
For example, I would require something like the following code:
Day <- c("Mo", "Mo", "Mo", "Tu", "Tu", "We", "We", "We", "We", "Th")
Val <- c(1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000)
df <- data.frame(cbind(Day,Val))
df$Adj <- ifelse(df$Day == "Mo" || df$Day == "Tu", 
                 as.numeric(levels(df$Val)) + 1, 
                 as.numeric(levels(df$Val)) + 2)
to return:
   Day  Val  Adj
1   Mo 1000 1001
2   Mo 1000 1001
3   Mo 1000 1001
4   Tu 1000 1001
5   Tu 1000 1001
6   We 1000 1002
7   We 1000 1002
8   We 1000 1002
9   We 1000 1002
10  Th 1000 1002
Unfortunately for me, my code instead returns Adj as a column of 1001s only.
   Day  Val  Adj
1   Mo 1000 1001
2   Mo 1000 1001
3   Mo 1000 1001
4   Tu 1000 1001
5   Tu 1000 1001
6   We 1000 1001
7   We 1000 1001
8   We 1000 1001
9   We 1000 1001
10  Th 1000 1001
I've tested the ifelse on one of the "We" rows and it does the trick ...
> ifelse(df$Day[6] == "Mo" || df$Day[6] == "Tu", 
+        as.numeric(levels(df$Val[6])) + 1, 
+        as.numeric(levels(df$Val[6])) + 2)
[1] 1002
... but I can't seem to get it to work on an entire column, which I had understood is one of the advantages of the ifelse function over a looped if-else statement.
I'm basing my approach off of the most similar questions I could find (Create new column in dataframe using if {} else {} in R) but have had no joy. What am I missing here?
We can use  %in% to check if Day has value as c('Mo', 'Tu'), add 1 or 2 accordingly to Val.
df <- transform(df, Adj = Val + ifelse(Day %in% c('Mo', 'Tu'), 1, 2))
#you can do this without `ifelse` as well.
#df <- transform(df, Adj = Val + as.integer(!Day %in% c('Mo', 'Tu')) + 1)
df
#   Day  Val  Adj
#1   Mo 1000 1001
#2   Mo 1000 1001
#3   Mo 1000 1001
#4   Tu 1000 1001
#5   Tu 1000 1001
#6   We 1000 1002
#7   We 1000 1002
#8   We 1000 1002
#9   We 1000 1002
#10  Th 1000 1002
                        With dplyr:
Day <- c("Mo", "Mo", "Mo", "Tu", "Tu", "We", "We", "We", "We", "Th")
Val <- c(1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000)
df <- data.frame(Day,Val)
library(dplyr)
df %>% rowwise %>% mutate(Adj = ifelse(Day == "Mo" || Day == "Tu", 
                           Val + 1, 
                           Val + 2))
#> # A tibble: 10 x 3
#>    Day     Val   Adj
#>    <chr> <dbl> <dbl>
#>  1 Mo     1000  1001
#>  2 Mo     1000  1001
#>  3 Mo     1000  1001
#>  4 Tu     1000  1001
#>  5 Tu     1000  1001
#>  6 We     1000  1002
#>  7 We     1000  1002
#>  8 We     1000  1002
#>  9 We     1000  1002
#> 10 Th     1000  1002
Note that df <- data.frame(cbind(Day,Val)) converts Val to character which is probably not what you're looking for.
You can simplify this to df <- data.frame(Day,Val)
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