【问题标题】:Conditional creation (mutate) of new columns有条件地创建(变异)新列
【发布时间】:2021-12-11 07:50:51
【问题描述】:

我有一个包含“潜在”列名的向量:

col_vector <- c("A", "B", "C")

我也有一个数据框,例如

library(tidyverse)
df <- tibble(A = 1:2,
             B = 1:2)

我现在的目标是创建 col_vector 中提到的所有在 df 中尚不存在的列。

对于上面的例子,我的代码如下:

df %>%
  mutate(!!sym(setdiff(col_vector, colnames(.))) := NA)

# A tibble: 2 x 3
      A     B C    
  <int> <int> <lgl>
1     1     1 NA   
2     2     2 NA  

问题是,一旦 a) 来自 col_vector 的多列丢失或 b) 没有来自 col_vector 的列,此代码就会失败。我考虑过某种 if_else,但不知道如何以这种方式使列创建有条件 - 最好以整洁的方式。我知道我可以创建一个遍历所有缺失列的循环,但我想知道是否有更直接的方法。

上述代码失败的示例数据:

df2 <- tibble(A = 1:2)
df3 <- tibble(A = 1:2,
              B = 1:2,
              C = 1:2)

【问题讨论】:

标签: r tidyverse


【解决方案1】:

这应该可行。

df[,setdiff(col_vector, colnames(df))] <- NA

【讨论】:

    【解决方案2】:

    解决方案

    这个base 操作可能比成熟的dplyr 工作流更简单:

    library(tidyverse) # For the setdiff() function.
    
    
    # ...
    # Code to generate 'df'.
    # ...
    
    
    # Find the subset of missing names, and create them as columns filled with 'NA'.
    df[, setdiff(col_vector, names(df))] <- NA
    
    
    # View results
    df
    

    结果

    在此处给出您的示例 col_vectordf

    col_vector <- c("A", "B", "C")
    df <- tibble(A = 1:2, B = 1:2)
    

    此解决方案应产生以下结果:

    # A tibble: 2 x 3
          A     B C    
      <int> <int> <lgl>
    1     1     1 NA   
    2     2     2 NA   
    

    优势

    above@geoff 链接的alternative 相比,我的解决方案的一个优势是您不需要手动对列名集进行编码,如symbols 和 dplyr 工作流程中的字符串。

    df %>% mutate(
      #####################################
      A = ifelse("A" %in% names(.), A, NA),
      B = ifelse("B" %in% names(.), B, NA),
      C = ifelse("C" %in% names(.), B, NA)
    
      # ...
      # etc.
      #####################################
    )
    

    相比之下,我的解决方案更加动态

         ##############################
    df[, setdiff(col_vector, names(df))] <- NA
         ##############################
    

    如果您决定在中途更改(甚至动态计算!)您的变量名称,因为它在运行时确定setdiff()

    注意

    令人难以置信的是,@AustinGraves posted 他们的answer 与我的posted 我的2021-10-25 21:03:05Z 在同一时间(2021-10-25 21:03:05Z),所以这两个答案都可以作为原始解决方案。

    【讨论】:

    • 不过,你的答案在几秒钟前就出现在我面前了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-04
    • 2015-04-26
    • 2020-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多