【问题标题】:Nested if statements inside case_when嵌套在 case_when 中的 if 语句
【发布时间】:2019-12-16 08:41:30
【问题描述】:

我正在尝试改变一个大型数据集,并且想知道是否有更好的方法来运行此代码:

library(dplyr)

df <- data.frame(id = c('person 1', 'person 2'), a1 = c(0, 1), a2 = c(1, 0), a3 = c(0, 0), b1 = c(0, 1), b3 = c(1, 0))

new_function = function(name){
    df %>% mutate(
    !!name := case_when( 
    if(any(names(df) == paste0(name,'_1'))){ !!sym(paste0(name,'1')) == 1 ~ 1 },
    if(any(names(df) == paste0(name,'_2'))){ !!sym(paste0(name,'2')) == 1 ~ 2 },
    if(any(names(df) == paste0(name,'_3'))){ !!sym(paste0(name,'3')) == 1 ~ 3 },
    TRUE ~ 0)
    )
}

col_names = c('a', 'b')

col_names %>%
    map(new_function) 

添加两个新列:

a = c(2,1)
b = c(3,1)

问题是向量 col_names 有一百多个条目,我不确定缺少哪些列。在case_when的每条语句中,为每个列名扫描整个数据框似乎效率很低。

我尝试使用可能()或安全()(没有 if 语句)来忽略错误并继续运行代码,但它给出了与以前相同的错误。

*注意每个人的每个字母只能有一个“1”,因此只有一个 case_when 语句可以评估为 TRUE。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    既然我们知道每个人在每个col_names 中只能有一个 1,我们可以利用这一事实来简化我们的逻辑。我们可以选择以col_names 开头的列,使用max.col 获取其中包含1 的列号,并通过从中删除所有非数字数据从列名返回值。

    library(dplyr)
    
    new_function <- function(x) {
      temp <- df %>% select(starts_with(x))
       as.integer(gsub("\\D", "", names(temp)[max.col(temp)]))
    }
    
    bind_cols(df, purrr::map_dfc(col_names, new_function))
    
    #        id a1 a2 a3 b1 b3 V1 V2
    #1 person 1  0  1  0  0  1  2  3
    #2 person 2  1  0  0  1  0  1  1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-06
      • 2012-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多