【问题标题】:Adding non existing columns to a data frame using mutate with across in dplyr R在 dplyr R 中使用 mutate with cross 将不存在的列添加到数据框中
【发布时间】:2022-08-23 12:18:24
【问题描述】:

我有一个列名列表如下,

cols <- c(\'grade\', \'score\', \'status\')

如果数据框在 cols 向量中没有任何列,我想使用 mutate 和 cross 将该列(值为 NA)添加到数据框中。怎么做?

  • 你会接受答案吗不是使用 dplyr mutate 和cross?我认为存在替代解决方案的问题例如this one

标签: r dataframe dplyr


【解决方案1】:

base 解决方案:

df[setdiff(cols, names(df))] <- NA

此命令可适用于管道:

df %>%
  `[<-`(, setdiff(cols, names(.)), NA)

#   id score grade status
# 1  1    94    NA     NA
# 2  2    98    NA     NA
# 3  3    93    NA     NA
# 4  4    82    NA     NA
# 5  5    89    NA     NA

数据
set.seed(123)
df <- data.frame(id = 1:5, score = sample(80:100, 5))

【讨论】:

  • 我接受这个答案,即使它不使用 mutate with cross ,因为它看起来更简单。谢谢
【解决方案2】:

使用dplyr::mutate() 的解决方案

假设您的数据框是diamonds。然后在原始数据帧(即diamond这里)中添加一个与列名(即在此MWE中为三列)具有相同列数的tibble数据框。

自动创建包含NA 的小标题

(感谢the commentDarren Tsai

要创建一个列数与列名相同的tibble,可以先创建一个matrix,其列数与matrix(ncol = length(cols))的列名相同,然后将其转换为tibble数据框通过as_tibble() 并在as_tibble() 中使用.name_repair = ~ cols 设置列名。

tibble 每一列的值是合乎逻辑的NA,创建矩阵时。请注意,如果您希望稍后将这些新添加的列更改为 integer 列、数字列、复杂列(例如 1 + 5i) 和字符列。在这种情况下,您可以mutate tibble 以便您可以更改列的类型。

您可以在 mutate 中创建这样的 tibble。

cols <- c('grade', 'score', 'status')

diamonds |>
  mutate(
    matrix(
      ncol = length(cols)
    ) |>
      as_tibble(
        .name_repair = ~ cols
      ) |>
      ## if you want to interpret the grade as `factor` type...
      mutate(
        grade = as.factor(grade)
      )
  )

## # A tibble: 53,940 × 13
##    carat cut       color clarity depth table price     x     y     z grade score
##    <dbl> <ord>     <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct> <lgl>
##  1  0.23 Ideal     E     SI2      61.5    55   326  3.95  3.98  2.43 NA    NA
##  2  0.21 Premium   E     SI1      59.8    61   326  3.89  3.84  2.31 NA    NA   
##  3  0.23 Good      E     VS1      56.9    65   327  4.05  4.07  2.31 NA    NA
##  4  0.29 Premium   I     VS2      62.4    58   334  4.2   4.23  2.63 NA    NA
##  5  0.31 Good      J     SI2      63.3    58   335  4.34  4.35  2.75 NA    NA
##  6  0.24 Very Good J     VVS2     62.8    57   336  3.94  3.96  2.48 NA    NA
##  7  0.24 Very Good I     VVS1     62.3    57   336  3.95  3.98  2.47 NA    NA   
##  8  0.26 Very Good H     SI1      61.9    55   337  4.07  4.11  2.53 NA    NA
##  9  0.22 Fair      E     VS2      65.1    61   337  3.87  3.78  2.49 NA    NA
## 10  0.23 Very Good H     VS1      59.4    61   338  4     4.05  2.39 NA    NA
## # … with 53,930 more rows, and 1 more variable: status <lgl>

创建没有与原始数据框匹配的任何列的NA tibble

(感谢the commentJulian

为确保仅当原始数据框没有cols 向量中的任何列时才将列添加到原始数据框中,您必须选择NA tibble 数据框中不包含的列存在于原始数据框中。您可以使用!select(matches(colnames(diamonds))) 来做到这一点。

cols <- c("grade", "price", "status")

matrix(ncol = length(cols)) |>
  as_tibble(
    .name_repair = ~ cols
  ) |>
  mutate(
    grade = as.factor(grade)
  )

diamonds |>
  mutate(
    matrix(
      ncol = length(cols)
    ) |>
      as_tibble(
        .name_repair = ~cols
      ) |>
      ## if you want to interpret the grade as `factor` type...
      mutate(
        grade = as.factor(grade)
      ) |>
      ## select columns that are not present in the original data frame 
      dplyr::select(
        !matches(colnames(diamonds))
      )
  )

## # A tibble: 53,940 × 12
##    carat cut      color clarity depth table price     x     y     z grade status
##    <dbl> <ord>    <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct> <lgl> 
##  1  0.23 Ideal    E     SI2      61.5    55   326  3.95  3.98  2.43 NA    NA
##  2  0.21 Premium  E     SI1      59.8    61   326  3.89  3.84  2.31 NA    NA
##  3  0.23 Good     E     VS1      56.9    65   327  4.05  4.07  2.31 NA    NA    
##  4  0.29 Premium  I     VS2      62.4    58   334  4.2   4.23  2.63 NA    NA
##  5  0.31 Good     J     SI2      63.3    58   335  4.34  4.35  2.75 NA    NA
##  6  0.24 Very Go… J     VVS2     62.8    57   336  3.94  3.96  2.48 NA    NA
##  7  0.24 Very Go… I     VVS1     62.3    57   336  3.95  3.98  2.47 NA    NA
##  8  0.26 Very Go… H     SI1      61.9    55   337  4.07  4.11  2.53 NA    NA    
##  9  0.22 Fair     E     VS2      65.1    61   337  3.87  3.78  2.49 NA    NA
## 10  0.23 Very Go… H     VS1      59.4    61   338  4     4.05  2.39 NA    NA
## # … with 53,930 more rows

【讨论】:

  • 这个想法总体上是好的,但是如果我理解正确,OP希望在数据中已经存在该列时保持不变,即在您的示例中,如果您将 cols 更改为cols &lt;- c('clarity', 'score', 'status'),您将看到清晰度为@987654350 @。
  • 此外,最好自动创建 tibble,而不是一一输入a = NAb = NA、...。如果cols 的长度为 100 怎么办?
  • @Julian 感谢您提供帮助的 cmets!我通过编辑我的答案来回复您的 cmets。
  • @DarrenTsai 谢谢你的好自然的问题!我改变了制作 tibble 的方式,并介绍了从矩阵自动制作 tibble 的方法。
【解决方案3】:
df <- data.frame(grade = c("A", "B", "C"),
                 score = c(1, 2, 3))

cols <- c('grade', 'score', 'status')

for (i in cols){
    if (!(i %in% colnames(df))){
        df[i] <- NA
    }
}

> df
  grade score status
1     A     1     NA
2     B     2     NA
3     C     3     NA

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-25
    • 1970-01-01
    • 2014-09-16
    • 2021-07-15
    • 2014-03-16
    • 2015-03-20
    • 2014-03-12
    相关资源
    最近更新 更多