Фильтровать NA по подмножеству столбцов, определенных как числовое имя

#r #pivot #tidyverse

#r #сводная #tidyverse

Вопрос:

Я пытаюсь отфильтровать все записи, содержащие систематический NA, по подмножеству числовых столбцов.

Вот игрушечный пример.

 library(tidyverse)

df <- tibble(
    year = c(2001, 2002, 2003, 2001, 2002, 2003, 2001),
    rank = c(12, 25, 65, NA, NA, NA, NA),
    category = c("a", "a", "b", "c", "c", "c", NA),
    other = c("x", "y", "x", "y", "x", "y", "x")
)

df %>%
    pivot_wider(names_from = year, values_from =  rank) %>%
    filter(.cols = c(2001:2003),
           .fns = ~ !is.na(.x))
 

Этот код не работает, он не может распознать столбцы 2001:2003 — Каков правильный способ удаления третьей записи путем фильтрации всех NA для столбцов 2001, 2002, 2003.
Диапазон столбцов должен быть указан как диапазон аналогично тому, как я делаю 2001: 2003.

Запись «c» должна быть отфильтрована, но не запись, в которой все столбцы являются NA (последний в примере с игрушкой)

Это ошибка, которую я получаю :

Ошибка: проблема с filter() вводом ..1 . Ввод x ..1 именован. ℹ Обычно это означает, что вы использовали = вместо == . ℹ Вы имели в виду .cols == c(2001:2003) ?

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

1. Вы хотите удалить категорию c, поскольку все с 2001 по 2003 год являются NAs?

2. Все записи, содержащие NA для столбцов 2011: 2003, выглядят как запись c , но она может быть любой другой

3. Почему не просто df %>% drop_na() %>% pivot_wider(...) ?

4. поскольку drop_na удалит все NA для всех столбцов, а не для 2001: 2003 — я уточню пример

5. Данные, с которыми я имею дело, представлены в широком формате, и именно так я должен их хранить — df это помощник.

Ответ №1:

Вы можете фильтровать по столбцам. Использовать across

 df %>% 
  pivot_wider(names_from = year, values_from =  rank) %>%
  filter(rowSums(!across(`2001`:`2003`, is.na)) > 0L)
 

Вывод

 # A tibble: 3 x 5
  category other `2001` `2002` `2003`
  <chr>    <chr>  <dbl>  <dbl>  <dbl>
1 a        x         12     NA     NA
2 a        y         NA     25     NA
3 b        x         NA     NA     65
 

Ответ №2:

Насколько мне известно, вы не можете фильтровать по столбцам. Вы можете выбирать только по столбцам. Вот что я бы сделал.

 df %>%
  pivot_wider(names_from = year, values_from =  rank) %>%
  pivot_longer(2:4) %>%
  group_by(name) %>%
  filter(!any(is.na(value)))
 

Ответ №3:

Возможно, было бы лучше filter перед выполнением pivot_wider

 library(dplyr)
library(tidyr)
df %>%
    group_by(category, other) %>% 
    filter(any(!is.na(rank))) %>% 
    ungroup %>%
    pivot_wider(names_from = year, values_from = rank)
 

-вывод

 # A tibble: 3 x 5
#  category other `2001` `2002` `2003`
#  <chr>    <chr>  <dbl>  <dbl>  <dbl>
#1 a        x         12     NA     NA
#2 a        y         NA     25     NA
#3 b        x         NA     NA     65
 

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

1. Действительно, но данные, с которыми я работаю, поступают в широкоформатном формате — я использовал игрушечный пример, чтобы перейти к формату моих данных, чтобы объяснить проблему.