Вложен 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
> 

вам, вероятно, нужен ifelse(), а не if/else, и даже лучше, вам, вероятно, нужен dplyr::case_when или data.table::fcase

MichaelChirico 25.06.2024 17:44

Вероятно, вам нужна функция ifelse, а не оператор if {} else {}, поскольку, похоже, вы намерены изменить несколько строк фрейма данных... @MichaelChirico: щелк!

Limey 25.06.2024 17:44

@MichaelChirico, попробовал dplry::case_when, возвращается NA.

Bubbles 25.06.2024 18:09
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
66
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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

Другие вопросы по теме

Есть ли лучший способ создать мой фрейм данных?
Как исправить столбец с числовыми значениями, который воспринимается как строковое поле из-за пустых строк в фрейме данных Pandas?
Добавьте значения двух Dataframe на основе похожих значений строк
Обмен датой начала, датой окончания и другими столбцами с более ранней строкой, если даты больше 8 в фрейме данных pandas
Почему сбор LazyFrame перед объединением в Polars решает мою проблему с несоответствиями индексов?
Python: только 2 уникальных имени столбца в фрейме данных, всего 3105 столбцов. Как получить среднее значение строки, сгруппированной по уникальному имени столбца
Как я могу сравнить значение в одном столбце со всеми значениями, которые находятся ДО него в другом столбце, чтобы найти количество уникальных значений, которые меньше?
Присоединиться к фрейму данных с двойной записью
Получите минимум за счет итераций записи в фрейме данных pandas
Добавьте количество строк в виде списка в столбец, используя groupby