I have the below data frame and would like to impose some rules to generate new values:
column_1<-c("B","B","B","B","A","A","A","A")
column_2<-c("L","L","B","B","L","L","B","B")
column_3<-c("c","b","c","b","c","b","c","b")
column_4<-rep(1)
column_5<-rep(0.5)
column_6<-rep(2)
df_test<-data.frame(column_1,column_2,column_3,column_4,column_5,column_6)
#concatenating column 1,2,3 as a flag, naming it column 7
df_test$column_7<-paste0(df_test$column_1,df_test$column_2,df_test$column_3)
> df_test
column_1 column_2 column_3 column_4 column_5 column_6 column_7
1 B L c 1 0.5 2 BLc
2 B L b 1 0.5 2 BLb
3 B B c 1 0.5 2 BBc
4 B B b 1 0.5 2 BBb
5 A L c 1 0.5 2 ALc
6 A L b 1 0.5 2 ALb
7 A B c 1 0.5 2 ABc
8 A B b 1 0.5 2 ABb
#rule 1: if column_7=="BLc|BBb", then df_test$result will be equal to column 4 +column 5 +column_6
#rule 2: if column_7=="BLb|BBc", then df_test$result will be equal to column 4 +column 5 -column_6
#rule 3: if column_7=="ALc|ABb", then df_test$result will be equal to column 4 -column 5 -column_6
#rule 4: if column_7=="ABc|ALb", then df_test$result will be equal to column 4 -column 5 +column_6
To convert the rules, I have the below snippet:
df_test$result<-if(df_test$column_7=="BLc|BBb"){
df_test$column_4+df_test$column_5+df_test$column_6
}else{
if(df_test$column_7=="BLb|BBc"){
df_test$column_4+df_test$column_5-df_test$column_6
}else{
if(df_test$column_7=="ALc|ABb"){
df_test$column_4-df_test$column_5-df_test$column_6
} else{
if(df_test$column_7=="ABc|ALb"){
df_test$column_4-df_test$column_5+df_test$column_6
}
}
}
}
Warning messages:
1: In if (df_test$column_7 == "BLc|BBb") { :
the condition has length > 1 and only the first element will be used
2: In if (df_test$column_7 == "BLb|BBc") { :
the condition has length > 1 and only the first element will be used
3: In if (df_test$column_7 == "ALc|ABb") { :
the condition has length > 1 and only the first element will be used
4: In if (df_test$column_7 == "ABc|ALb") { :
the condition has length > 1 and only the first element will be used
> print(df_test$result)
NULL
Here I assume the way I nest with if else goes wrong, can you please give me some hints on it?
If everything goes right, the below is expected to be seen:
> data.frame(desired_column_8)
desired_column_8
1 3.5
2 -0.5
3 -0.5
4 3.5
5 -1.5
6 2.5
7 2.5
8 -1.5
Anyway, thanks all for taking time to view this post.
Update 1: Try dplyr::case_when
library(dplyr)
df_test<-df_test %>%
mutate(column_8=case_when(column_7=="BLc|BBb" ~df_test$column_4+df_test$column_5+df_test$column_6,
column_7=="BLb|BBc" ~df_test$column_4+df_test$column_5-df_test$column_6,
column_7=="ALc|ABb" ~df_test$column_4-df_test$column_5-df_test$column_6,
column_7=="ABc|ALb"~df_test$column_4-df_test$column_5+df_test$column_6))
> df_test
column_1 column_2 column_3 column_4 column_5 column_6 column_7 column_8
1 B L c 1 0.5 2 BLc NA
2 B L b 1 0.5 2 BLb NA
3 B B c 1 0.5 2 BBc NA
4 B B b 1 0.5 2 BBb NA
5 A L c 1 0.5 2 ALc NA
6 A L b 1 0.5 2 ALb NA
7 A B c 1 0.5 2 ABc NA
8 A B b 1 0.5 2 ABb NA
>
An option using match
. It may be more performant than nested ifelse
s.
codes <- c("BLc", "BBb", "BLb", "BBc", "ABc", "ALb", "ALc", "ABb")
transform(
df_test,
result = {
i <- (match(column_7, codes) - 1)%/%2
column_4 + column_5*(1 - 2*(i%/%2)) + column_6*(1 - 2*(i%%2))
}
)
#> column_1 column_2 column_3 column_4 column_5 column_6 column_7 result
#> 1 B L c 1 0.5 2 BLc 3.5
#> 2 B L b 1 0.5 2 BLb -0.5
#> 3 B B c 1 0.5 2 BBc -0.5
#> 4 B B b 1 0.5 2 BBb 3.5
#> 5 A L c 1 0.5 2 ALc -1.5
#> 6 A L b 1 0.5 2 ALb 2.5
#> 7 A B c 1 0.5 2 ABc 2.5
#> 8 A B b 1 0.5 2 ABb -1.5