У меня есть приведенный ниже фрейм данных, и я хотел бы ввести некоторые правила для создания новых значений:
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 {}
, поскольку, похоже, вы намерены изменить несколько строк фрейма данных... @MichaelChirico: щелк!
@MichaelChirico, попробовал dplry::case_when, возвращается NA.
Вариант с использованием 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
вам, вероятно, нужен ifelse(), а не if/else, и даже лучше, вам, вероятно, нужен dplyr::case_when или data.table::fcase