R语言 使用case_when/if_any跨多个变量创建变量

bkhjykvo  于 2023-02-01  发布在  其他
关注(0)|答案(1)|浏览(237)

我有一个数据集,其中一些变量的名称对应于每个月(例如var1_M1、var1_M2、var2_M1 ...),我需要按每个月进行汇总(在条件之后),并在发现值〉90时识别第一个案例,最后指示相应的月份。

library(dplyr)

ID <- c("Dave", "Joe", "Steve")
var1_M1 <- c(10, 10, 90)
var1_M2 <- c(30, 90, 95)
var1_M3 <- c(90, 100, 95)
var2_M1 <- c(10, 90, 20)
var2_M2 <- c(33, 10, 100)
var2_M3 <- c(90, 10, 50)

data <- tibble(ID, var1_M1, var1_M2, var1_M3, var2_M1, var2_M2, var2_M3)

# A tibble: 3 x 7
  ID    var1_M1 var1_M2 var1_M3 var2_M1 var2_M2 var2_M3
  <chr>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
1 Dave       10      30      90      10      33      90
2 Joe        10      90     100      90      10      10
3 Steve      90      95      95      20     100      50

data %>% 
  mutate_at(vars(matches(c("M1","M2","M3"))),
            list(~ ifelse(. > 90, .,0))) #%>% 
  #mutate() using map_dfc and if_any ??

预期输出

# A tibble: 3 x 5
  ID       M1    M2    M3 output
  <chr> <dbl> <dbl> <dbl>  <dbl>
1 Dave      0     0     0      0
2 Joe       0     0   100      3
3 Steve     0   195    95      2
v8wbuo2f

v8wbuo2f1#

我们可以使用pivot_longer将其重新整形为"long"格式,按"ID"分组,获取sumacross列,其中值大于90,并使用max.col创建第一列索引值不为0的output

library(tidyr)
library(dplyr)
pivot_longer(data, cols = -ID, names_to = c(".value"), 
   names_pattern = ".*_(.*)") %>%
   group_by(ID) %>% 
   summarise(across(everything(), ~ sum(.x[.x > 90]))) %>% 
   mutate(output = max.col(across(starts_with("M")) >0, "first") * 
     if_any(starts_with("M"), ~ .x > 0))
  • 输出
# A tibble: 3 × 5
  ID       M1    M2    M3 output
  <chr> <dbl> <dbl> <dbl>  <int>
1 Dave      0     0     0      0
2 Joe       0     0   100      3
3 Steve     0   195    95      2

对于pivot_longer,我们在names_pattern中指定了一个正则表达式,以将_之后的字符捕获为一个组列名(即M1M2M3)中的((...))使用.*-匹配零个或多个字符,并将names_to指定为.value,以便将其整形为长格式,列名为M1M2M3,并组合所有var_列。
summarisesum相乘后,使用max.col查找大于0的列值的第一个索引。在第一行(即Dave id)中,所有值均为0,因此max.col返回索引1。要使其为0,请与if_any的TRUE/FALSE输出相乘(TRUE-〉1,FALSE-〉0)。即,创建一个列以更好地理解它可能更好

pivot_longer(data, cols = -ID, names_to = c(".value"), 
   names_pattern = ".*_(.*)") %>%
   group_by(ID) %>% 
   summarise(across(everything(), ~ sum(.x[.x > 90]))) %>%
   mutate(if_any_ind = if_any(starts_with("M"), ~ .x > 0),
           output_ind =max.col(across(starts_with("M")) >0, "first"),
           output = if_any_ind * output_ind)
  • 输出
# A tibble: 3 × 7
  ID       M1    M2    M3 if_any_ind output_ind output
  <chr> <dbl> <dbl> <dbl> <lgl>           <int>  <int>
1 Dave      0     0     0 FALSE               1      0
2 Joe       0     0   100 TRUE                3      3
3 Steve     0   195    95 TRUE                2      2

即任何值x0-〉0和值x1-〉1

相关问题