Добавить столбец к элементам в списке фреймов данных

У меня есть список фреймов данных, где у некоторых есть столбец need, а у других нет. Как добавить столбец need к другим фреймам данных (со значением = NA)? Я пробовал использовать Map или lapply

test <- list(data.frame(need = NA, dont_need = NA),
             data.frame(dont_need = NA),
             data.frame(dont_need = NA, dont_need_2 = NA))

Желаемый результат

[[1]]
  need dont_need
1   NA        NA

[[2]]
  dont_need need
1        NA   NA

[[3]]
  dont_need dont_need_2 need
1        NA          NA   NA

Я не могу просто использовать привязку, потому что этот список создается динамически и иногда включает только один фрейм данных, в котором нет столбца need. Ответ также должен работать, когда это так:

test_2 <- list(data.frame(dont_need = NA))

person MayaGans    schedule 06.02.2020    source источник


Ответы (4)


Одна purrr возможность для ситуаций, когда есть только пустые элементы, может быть:

map(test, ~ list_modify(., need = NA))

[[1]]
  need dont_need
1   NA        NA

[[2]]
  dont_need need
1        NA   NA

[[3]]
  dont_need dont_need_2 need
1        NA          NA   NA

Если бы могли существовать непустые элементы:

map(test, ~ if(!"need" %in% names(.)) update_list(., need = NA) else .)
person tmfmnk    schedule 06.02.2020
comment
вы должны включить library(purrr) в свой ответ, чтобы сделать его более понятным для людей, которые этого не знают. - person Gallarus; 06.02.2020
comment
На самом деле этот ответ удалит значения в столбцах need, если они уже существуют и не являются NA - person Gallarus; 06.02.2020
comment
@Gallarus, именно по этой причине я также включил решение для непустых существующих элементов. - person tmfmnk; 06.02.2020
comment
я плохо себя чувствую, я был слишком быстр в своих суждениях, извините - person Gallarus; 06.02.2020

Другая версия с использованием lapply и is.null. Я добавил некоторые реальные значения в начальный data.frame, чтобы показать, что они сохраняются, если они присутствуют изначально.

test <- list(data.frame(need = c(NA, 2), dont_need = 1:2),
             data.frame(dont_need = 1:3),
             data.frame(dont_need = 1:3, dont_need_2 = NA))
> [[1]]
> need dont_need
> NA         1
>  2         2
> 
> [[2]]
> dont_need
>  1
>  2
>  3
> 
> [[3]]
> dont_need dont_need_2
>  1          NA
>  2          NA
>  3          NA


test <- lapply(test, function(df) {
  if (is.null(df[["need"]])) 
    df[["need"]] <- NA

  df
})

> [[1]]
> need dont_need
>  NA         1
>   2         2
> 
> [[2]]
> dont_need need
>  1   NA
>  2   NA
>  3   NA
> 
> [[3]]
> dont_need dont_need_2 need
>  1          NA   NA
>  2          NA   NA
>  3          NA   NA
person Gallarus    schedule 06.02.2020
comment
Благодарю вас! В спешке, чтобы сделать повторение, я понял, что отсутствие значений в исходном фрейме данных сбивает с толку ответ, поскольку ниже люди предложили заменить все потребности на NA. - person MayaGans; 06.02.2020
comment
Ответ purrr от @tmfmnk на самом деле правильный, а я ошибался. Я предоставляю версию, которая не удаляет уже имеющиеся значения. - person Gallarus; 06.02.2020

Вот простой способ использования lapply:

test <- list(data.frame(need = NA, dont_need = NA),
             data.frame(dont_need = NA),
             data.frame(dont_need = NA, dont_need_2 = NA))


lapply(test, function(df) {
  if (!"need" %in% colnames(df)) {
    df$need <- NA
  }
  return(df)
})
#> [[1]]
#>   need dont_need
#> 1   NA        NA
#> 
#> [[2]]
#>   dont_need need
#> 1        NA   NA
#> 
#> [[3]]
#>   dont_need dont_need_2 need
#> 1        NA          NA   NA

Создана 06 февраля 2020 г. с помощью пакета reprex (v0.3.0)

person JBGruber    schedule 06.02.2020

Вы можете написать функцию, которая проверяет имена столбцов каждого data.frame для need, а затем создает ее, если ее там нет.

test2 <- lapply(test, function(x) {
  if(!"need"%in% colnames(x)){
    x$need <- NA
  }
  return(x)
})

[[1]]
  need dont_need
1   NA        NA

[[2]]
  dont_need need
1        NA   NA

[[3]]
  dont_need dont_need_2 need
1        NA          NA   NA
person mfidino    schedule 06.02.2020