Проверка наличия NAs по строкам, затем агрегирование имен их столбцов

#r #dataframe #dplyr #slice #na

#r #фрейм данных #dplyr #срез #na

Вопрос:

В настоящее время я изо всех сил пытаюсь получить информацию по строкам, по которым переменные оказались хорошими / которые являются NA. Ниже я показываю пример / вывод dput части моих данных.

 head(big_test)
# A tibble: 3 x 19
     id ctr_n   ctr    yr    mn  nvvi ENP_nat ENP_avg ENP_wght inflation1 inflation2 inflation3 inflation4 PSNS  PSNS_s PSNS_w
  <dbl> <chr> <dbl> <dbl> <dbl> <dbl>   <dbl>   <dbl>    <dbl> <chr>      <chr>      <chr>      <chr>      <chr>  <dbl> <chr> 
1  1854 Isra~   376  2019     4     1    3.50    3.50     3.50 NA         NA         NA         NA         NA     0.962 NA    
2  1855 Isra~   376  2019     9     1    2.51    2.51     2.51 NA         NA         NA         NA         NA     0.992 NA    
3  1856 Isra~   376  2020     3     1    3.78    3.78     3.78 NA         NA         NA         NA         NA     0.999 NA    
# ... with 3 more variables: PSNS_sw <chr>, local_E <dbl>, cst_tot <dbl>

dput(big_test)
structure(list(id = c(1854, 1855, 1856), ctr_n = c("Israel", 
"Israel", "Israel"), ctr = c(376, 376, 376), yr = c(2019, 2019, 
2020), mn = c(4, 9, 3), nvvi = c(1, 1, 1), ENP_nat = c(3.50348063163162, 
2.51319610127466, 3.78468892335972), ENP_avg = c(3.50348063163162, 
2.51319610127466, 3.78468892335972), ENP_wght = c(3.50348063163162, 
2.51319610127466, 3.78468892335972), inflation1 = c("NA", "NA", 
"NA"), inflation2 = c("NA", "NA", "NA"), inflation3 = c("NA", 
"NA", "NA"), inflation4 = c("NA", "NA", "NA"), PSNS = c("NA", 
"NA", "NA"), PSNS_s = c(0.961748183147869, 0.992275075925835, 
0.998547438416594), PSNS_w = c("NA", "NA", "NA"), PSNS_sw = c("NA", 
"NA", "NA"), local_E = c(1, 1, 1), cst_tot = c(1, 1, 1)), row.names = c(NA, 
-3L), class = c("tbl_df", "tbl", "data.frame"))
  

РЕДАКТИРОВАТЬ: NAs здесь заключены в кавычки, что неуместно. Я думаю, что проблема возникла из-за записи в .xlsx; правильная версия указана ниже в dput выводе без кавычек на NAs.

Как вы можете видеть, данные разделены на национальном уровне по выборам, где каждая строка здесь должна быть уникальной (т.Е. Израиль, 2019 год, месяц 4). Я хочу создать символьный столбец, в котором перечислены переменные, отсутствующие в этом выводе.Вот пример требуемого столбца:

 desired_output <- tibble(missing_vars=paste("inflation1","inflation2","inflation3","inflation4","etc",sep=";"))

head(desired_output)
# A tibble: 1 x 1
  missing_vars                                   
  <chr>                                          
1 inflation1;inflation2;inflation3;inflation4;etc
  

Таким образом, мне интересно, существует ли какой-то цикл, который может нарезать уникальные выборы, посмотреть на отсутствующие столбцы, а затем перенести те, которые отсутствуют? Это крайне важно для автоматизации, поскольку некоторые переменные могут отсутствовать там, где другие присутствуют для той же страны / года. Я пытался их посчитать, но не могу понять, как перечислить эти имена столбцов в виде символьного столбца.

Любая помощь приветствуется. Спасибо!

Комментарии:

1. У вас есть NA как строка. Вместо этого оно должно быть без кавычек

2. Хм, это может быть странной проблемой с запросом вышестоящего начальника на использование .xlsx; это определенно изменит это.

Ответ №1:

Вот вариант tidyverse , в котором мы изменяем формат на «длинный» pivot_longer , сгруппировав по row_number() paste именам столбцов, где в «значении» отсутствует значение

 library(dplyr)
library(tidyr)
library(stringr)
big_test %>%
     select(starts_with('inflation')) %>% 
     mutate(rn = row_number()) %>% 
     pivot_longer(cols = -rn) %>% 
     group_by(rn) %>%
     summarise(missing_vars = str_c(name[is.na(value)], collapse=";"),
          .groups = 'drop') %>%
     select(-rn)          
  

Без изменения формы можно rowwise/c_across

 big_test %>% 
   rowwise %>% 
   transmute(missing_vars = str_c(names(select(cur_data(), 
      starts_with('inflation')))[which(c_across(starts_with('inflation')) 
        == 'NA')], collapse=";"))
  

Здесь он сравнивает ( == ) с «NA». Если это реальное NA значение, используйте is.na вместо ==

Комментарии:

1. Спасибо за tidyverse ответ и указание на странную проблему NA!

Ответ №2:

Как отметил @akrun, у вас есть строки «NA» вместо NA. Как только это исправлено, вы можете определить отсутствующую функцию и применить ее к каждой строке для создания новой переменной:

 big_test <- structure(list(id = c(1854, 1855, 1856), ctr_n = c("Israel", 
"Israel", "Israel"), ctr = c(376, 376, 376), yr = c(2019, 2019, 
2020), mn = c(4, 9, 3), nvvi = c(1, 1, 1), ENP_nat = c(3.50348063163162, 
2.51319610127466, 3.78468892335972), ENP_avg = c(3.50348063163162, 
2.51319610127466, 3.78468892335972), ENP_wght = c(3.50348063163162, 
2.51319610127466, 3.78468892335972), inflation1 = c(NA, NA, 
NA), inflation2 = c(NA, NA, NA), inflation3 = c(NA, 
NA, NA), inflation4 = c(NA, NA, NA), PSNS = c(NA, 
NA, NA), PSNS_s = c(0.961748183147869, 0.992275075925835, 
0.998547438416594), PSNS_w = c(NA, NA, NA), PSNS_sw = c(NA, 
NA, NA), local_E = c(1, 1, 1), cst_tot = c(1, 1, 1)), row.names = c(NA, 
-3L), class = c("tbl_df", "tbl", "data.frame"))

missing <- function(x) {
  idx <- is.na(unlist(x))
  paste(colnames(big_test)[idx], collapse=", ")
}

big_test$missing <- apply(big_test, 1, missing)

big_test$missing
#> [1] "inflation1, inflation2, inflation3, inflation4, PSNS, PSNS_w, PSNS_sw"
#> [2] "inflation1, inflation2, inflation3, inflation4, PSNS, PSNS_w, PSNS_sw"
#> [3] "inflation1, inflation2, inflation3, inflation4, PSNS, PSNS_w, PSNS_sw"
  

Комментарии:

1. Верно; думал, что это была проблема при записи в .xlsx, но, безусловно, это легко исправить. Спасибо за элегантное решение! Я выберу это в качестве ответа, как только это позволит мне через несколько минут.