Как подсчитать уникальные значения в R, игнорируя NAs

#r #data.table

#r #data.table

Вопрос:

Это мои входные данные

 key     col_a      col_b      
  a       QQQ       <NA>    
  a       QQC       <NA>    
  b      <NA>        ACQ    
  b      <NA>        ACQ    
  
  

Я хотел бы создать этот вывод

   key     col_a      col_b      
    a         2          0    
    b         0          1    
  
  

Я пытался сделать это с помощью length(unique(x $ col_a)), но он считает NA как значения

Я создаю этот объект с помощью data.tables, и он исходит из инструкции ifelse().

Могу ли я изменить значение, которое я ввожу в инструкцию ifelse, на что-то другое или считать уникальные, игнорируя NAs?

Ответ №1:

Для каждого key мы можем узнать уникальные значения в столбцах с n_distinct

 library(dplyr)

df %>%
  group_by(key) %>%
  summarise(across(col_a:col_b, n_distinct, na.rm = TRUE))
  

В data.table это можно сделать как :

 library(data.table)
setDT(df)[, lapply(.SD, uniqueN, na.rm = TRUE), key, .SDcols = col_a:col_b]

   key col_a col_b
1:   a     2     0
2:   b     0     1
  

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

1. Потрясающе, я отмечу, что n_distinct также имеет na.rm=T

2. Это даже лучше. Спасибо. Я обновил ответ, чтобы включить это.

3. Что такое .SD во второй части?

4. В data.table вы можете указать столбцы, к которым хотите применить функцию с .SDcols . В lapply мы используем .SD для ссылки на эти столбцы.

Ответ №2:

Мы можем использовать base R методы для этого

 aggregate(. ~ key, df, FUN = function(x)
      length(unique(na.omit(x))), na.action = NULL)
#    key col_a col_b
#1   a     2     0
#2   b     0     1
  

Или с tidyverse использованием анонимной функции

 library(dplyr)
df %>% 
     group_by(key) %>% 
     summarise(across(everything(), ~ n_distinct(., na.rm = TRUE)))
  

данные

 df <- structure(list(key = c("a", "a", "b", "b"), col_a = c("QQQ", 
"QQC", NA, NA), col_b = c(NA, NA, "ACQ", "ACQ")),
class = "data.frame", row.names = c(NA, 
-4L))