#r
Вопрос:
Я пытаюсь подсчитать количество NA в нескольких столбцах моих данных. Вот воспроизводимый образец.
structure(list(V2QE38A = c(1, 0, 1, 0, 1, 1, 1, 0, 1, 0), V2QE38B = c(0,
0, 0, 0, 0, 1, 0, 0, 0, 0), V2QE38C = c(1, 1, 0, 3, 2, 0, 0,
3, 1, 1), V2QE38D = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), row.names = c(NA,
10L), class = "data.frame")
Я попробовал два метода:
Первый:
dt %>% select(starts_with("V2QE38")) %>% colSums(is.na(.))
И это дает мне некоторые результаты (короче говоря, у меня есть NAs в некоторых столбцах).
Затем я попробовал еще один:
colSums(is.na(dt[,c("V2QE38A", "V2QE38B", "V2QE38C", "V2QE38D")]))
И я не обнаружил ни в одной из этих колонок NA.
Я думаю, что второй результат верен. Но мне просто интересно, что я сделал не так, чтобы получить первый результат? Спасибо!
Ответ №1:
В первом случае передается несколько функций. Возможно, нам придется либо заблокировать его с помощью {}
library(dplyr)
dt %>%
select(starts_with("V2QE38")) %>%
{colSums(is.na(.))}
V2QE38A V2QE38B V2QE38C V2QE38D
0 0 0 0
или выпейте еще %>%
dt %>%
select(starts_with("V2QE38")) %>%
is.na %>%
colSums
-выход
V2QE38A V2QE38B V2QE38C V2QE38D
0 0 0 0
Проблема в том, что colSums
сначала выполняется без оценки is.na
> dt %>%
select(starts_with("V2QE38")) %>%
colSums(.)
V2QE38A V2QE38B V2QE38C V2QE38D
6 1 12 0
что совпадает с выводом операции с colSums(is.na(.))
Комментарии:
1. Я вижу! Большое вам спасибо за ответ. Очень ясно!
2. @YYM17 По умолчанию первый аргумент берется из lhs of
%>%
. второй аргументcolSums
исna.rm
, который берется вdt %>% select(starts_with("V2QE38")) %>% colSums(na.rm = is.na(.))
3. Да, мне просто нужно подождать еще пару минут, чтобы система разрешила принять ответ, Хахахаха
4. @YYM17 вы можете проверить эти ` ДТ %>% выберите(starts_with(«V2QE38″)) %>% colSums(размеры= это.на(.)) Ошибка в colSums(., размеры = это.на(.)) : недопустимое ‘затемняет» или
dt %>% select(starts_with("V2QE38")) %>% colSums(x= is.na(.))
не будет работать, так как ее уже успели оценитьx
от лхс5. Спасибо! Кажется, что логика, лежащая в основе colSums, немного странна внутри трубы
Ответ №2:
Базовое решение с использованием sapply
и одноименной функции function(x){sum(is.na(x))}
:
data = structure(list(V2QE38A = c(1, 0, 1, 0, 1, 1, 1, 0, 1, 0), V2QE38B = c(0,
0, 0, 0, 0, 1, 0, 0, 0, 0), V2QE38C = c(1, 1, 0, 3, 2, 0, 0,
3, 1, 1), V2QE38D = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), row.names = c(NA,
10L), class = "data.frame")
sapply(data, function(x){sum(is.na(x))})
# V2QE38A V2QE38B V2QE38C V2QE38D
# 0 0 0 0
Объяснение:
sapply
применяет функцию к a list
. data.frame
представляет собой список, каждый вектор которого является элементом этого списка. Вход s
sapply
предназначен для упрощения, поэтому sapply
мы попытаемся преобразовать выходной список (из lapply
) в вектор. Если требуемым выводом является список (у него есть некоторые преимущества), используйте lapply
вместо этого.
is.na
возвращает логический TRUE/FALSE
вектор. Это можно преобразовать в числовой вектор со 1/0
значениями.
sum
преобразует TRUE/FALSE
вектор в 1/0
вектор и суммирует значения.
Альтернативные решения:
В качестве альтернативы, вместо того, чтобы рассматривать data.frame
его как список, рассматривайте его как матрицу. Тогда сильно оптимизированный rowSums
и colSums
может вступить в игру.
colSums(is.na(data))
# V2QE38A V2QE38B V2QE38C V2QE38D
# 0 0 0 0
rowSums(is.na(data))
# 1 2 3 4 5 6 7 8 9 10
# 0 0 0 0 0 0 0 0 0 0
Это здорово, если у вас есть matrix
» а «и вы хотите найти, где NA
находятся «с».
Комментарии:
1. Спасибо! Хотя до этого я пробовал
apply
, но есть некоторые проблемы, когда я пытался совместить это сdplyr
. Приятно знать, чтоsapply
это можно использовать вместо этого!