【问题标题】:Using mutate to create new category conditional on dynamically named columns使用 mutate 以动态命名的列为条件创建新类别
【发布时间】:2023-03-30 13:52:01
【问题描述】:

我正在尝试根据另一组列的值创建一个新列category。但是,我想动态选择要作为条件的列,而不是对列名进行硬编码。如果可能的话,我想留在 tidyverse。

这是我的最小可重现示例:

library(dplyr)

df <- tibble(user = c("A", "B", "C", "D", "E"),
       jan = c(200, 500, 0, 20, 0),
       feb = c(50, 10, 0, 0, 50),
       mar = c(10, 100, 20, 0, 0),
       apr = c(500, 10, 0, 20, 0))

category 列应包含值“稳定”,如果该行在过去 3 个月的每个月中都有非零值。这段代码可以满足我的要求:

df %>%
  mutate(category = if_else(feb != 0 & mar != 0 & apr != 0, "stable", NA_character_))

但是,如果我想每月运行此代码(在添加新月份的数据后),我将不断更新它以引用最近 3 个月的列名。

有没有办法动态地做到这一点?我尝试将列位置与last_col(offset = 2:0) 一起使用,但没有成功。任何帮助将不胜感激。

【问题讨论】:

  • dplyr 中,您可能需要执行以下操作:name_vec &lt;- tail(names(df),3) df %&gt;% mutate(category = if_else(!!sym(name_vec[1])!= 0 &amp; !!sym(name_vec[2]) != 0 &amp; !!sym(name_vec[3]) != 0, "stable", NA_character_))

标签: r


【解决方案1】:

我认为使用 base R 会很简单,你可以这样做

n <- 3
df$category <- c(NA, "stable")[(rowSums(df[tail(names(df), n)] != 0) == n) + 1]

#  user    jan   feb   mar   apr category
#  <chr> <dbl> <dbl> <dbl> <dbl> <chr>   
#1 A       200    50    10   500 stable  
#2 B       500    10   100    10 stable  
#3 C         0     0    20     0 NA      
#4 D        20     0     0    20 NA      
#5 E         0    50     0     0 NA      

【讨论】:

  • 我没有想到将 rowSums 与逻辑向量一起使用,但这是获得所需输出的一种优雅方式。我的实际代码有一堆 case_when 语句,这是其中一种情况,因此基于 dplyr 的解决方案将更容易集成(这就是我接受@arg0naut91 提供的答案的原因)。但是,非常感谢您提出实现这一目标所需的逻辑!
【解决方案2】:

Ronak Shah 的回答中已经包含了基本逻辑,但这可能是dplyr 的一种可能方式:

n <- 3

df %>%
  mutate(
    category = ifelse(
      rowSums(select(., last_col(offset = 0:(n-1))) == 0) > 0, 
      NA_character_, 
      "stable")
  )

【讨论】:

  • 感谢 arg0naut91!只是出于好奇,为什么选择调用中需要 . 提供给 rowSums?
  • 删除它会失败 - rowSums 需要一个数组,您需要使用普通的 select 语句生成它,否则它将无法在 mutate 中工作。
  • 啊,我明白了。再次感谢!
猜你喜欢
  • 2023-04-09
  • 2018-10-03
  • 1970-01-01
  • 2018-03-06
  • 1970-01-01
  • 1970-01-01
  • 2021-10-27
  • 1970-01-01
  • 2017-08-12
相关资源
最近更新 更多