Вложен ifelse в R с предупреждением «условие имеет длину > 1»

У меня есть приведенный ниже фрейм данных, и я хотел бы ввести некоторые правила для создания новых значений:

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

Чтобы преобразовать правила, у меня есть фрагмент ниже:

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

Здесь я предполагаю, как я вставляю, если что-то пойдет не так, не могли бы вы дать мне несколько советов по этому поводу?

Если все пойдет правильно, ожидается следующее:

> 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

В любом случае, спасибо всем, что нашли время просмотреть этот пост.

Обновление 1: попробуйте 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
> 

66
3

Ответы:

Решено

Вариант с использованием match. Это может быть более производительно, чем вложенные ifelse.

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

Вы можете решить свою проблему, используя регулярное выражение, следующим образом:

library(dplyr)
library(stringr)

df_test %>%
  mutate(column_8=case_when(str_detect(column_7, "BLc|BBb") ~ column_4 + column_5 + column_6,
                            str_detect(column_7, "BLb|BBc") ~ column_4 + column_5 - column_6,
                            str_detect(column_7, "ALc|ABb") ~ column_4 - column_5 - column_6,
                            str_detect(column_7, "ABc|ALb") ~ column_4 - column_5 + column_6))

  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      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

Другое решение с использованием dplyr::case_match():

library(dplyr)
df_test |>
  mutate(
    column_8 = case_match(
      column_7,
      c("BLc", "BBb") ~ column_4 + column_5 + column_6,
      c("BLb", "BBc") ~ column_4 + column_5 - column_6,
      c("ALc", "ABb") ~ column_4 - column_5 - column_6,
      c("ABc", "ALb") ~ column_4 - column_5 + column_6)
  )

Выход:

  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      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