我想知道,是否有更直接的解决以下问题的方法。我想用符号和与分类列相关的条件分隔数字列中的值。
如果这是我的数据帧:
library(tidyverse)
a <- tribble(
~category , ~val ,
'A' , 1 ,
'A' , -1 ,
'B' , -2 ,
'C' , 1 ,
'Z' , 3 ,
'Z' , -4
)
我想创建四个新列,如果类别= 'Z',则为正负值,如果类别== 'Z,则为正负值
下面的代码产生了期望的结果:
a %>%
mutate(good = if_else(category != 'Z' & val >= 0 , val , 0) ,
bad = if_else(category != 'Z' & val < 0 , val , 0) ,
reserve = if_else(category == 'Z' & val >= 0 , val , 0) ,
risk = if_else(category == 'Z' & val < 0 , val , 0))
但是,由于我有许多类别和值列,以及许多将它们分开的规则,我最终会得到大量的if-else条件。有人知道更直接的解决方法吗?
思路与上一个答案相似。按条件划分类别,然后再扩大范围。下面我将向您展示如何使用将逻辑语句转换为数字索引来索引类别。
library(tidyverse)
a |>
mutate(grp = c("bad", "good", "risk", "reserve")[
(val>0) + (category == "Z") + (val<0 & category == "Z") + (val>0 & category == "Z") +1
],
id = row_number()) |>
pivot_wider(names_from = grp, values_from = val, values_fill = 0) |>
select(-id)
#> # A tibble: 6 x 5
#> category good bad reserve risk
#> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 A 1 0 0 0
#> 2 A 0 -1 0 0
#> 3 B 0 -2 0 0
#> 4 C 1 0 0 0
#> 5 Z 0 0 3 0
#> 6 Z 0 0 0 -4
如果你可以放弃val
列,我会这样做:
library(tidyverse)
a <- tribble(
~category , ~val ,
'A' , 1 ,
'A' , -1 ,
'B' , -2 ,
'C' , 1 ,
'Z' , 3 ,
'Z' , -4
)
a2 <- a %>%
mutate(
condition = case_when(
category != 'Z' & val >= 0 ~ 'good',
category != 'Z' & val < 0 ~ 'bad',
category == 'Z' & val >= 0 ~ 'reserve',
category == 'Z' & val < 0 ~'risk'
)
)
a2 %>%
rownames_to_column(".flag.row") %>%
pivot_wider(
names_from = 'condition',
values_from = 'val',
values_fill = 0
) %>%
select(-.flag.row)