2

我有不同类型变量的数据。有些是字符,有些是因数,有些是数字,如下所示:

df <- data.frame(a = c("tt", "ss", "ss", NA), b=c(2,3,NA,1), c=c(1,2,NA, NA), d=c("tt", "ss", "ss", NA))

我正在尝试使用c_acrossin计算每个观察值的缺失值数量dplyr 但是,c_across似乎无法组合不同类型的值,如下面的错误消息所示

df %>%
  rowwise() %>%
  summarise(NAs = sum(is.na(c_across())))

错误:summarise()输入有问题NAs。x 不能组合a<因子> 和b. ℹ 输入NAssum(is.na(c_across()))。ℹ 错误发生在第 1 行。

事实上,如果我只包含数字变量,它就可以工作。

df %>%
  rowwise() %>%
  summarise(NAs = sum(is.na(c_across(b:c))))

如果我只包含字符变量,同样的事情

df %>%
  rowwise() %>%
  summarise(NAs = sum(is.na(c_across(c(a,d)))))

我可以不使用下面的方法来解决这个问题c_across,但是我有很多变量,所以它不是很实用。

df %>%
  rowwise() %>%
  summarise(NAs = is.na(a)+is.na(b)+is.na(c)+is.na(d))

我可以使用传统apply方法,如下所示,但我想使用dplyr.

apply(df, 1, function(x)sum(is.na(x)))

关于如何计算缺失值数量、逐行、高效和使用的任何建议dplyr

4

2 回答 2

2

我会建议这种方法。问题是因为两件事。首先,数据框中的变量类型不同,其次,您需要一个用于按行样式任务的关键变量。因此,在接下来的代码中,我们首先将变量转换为类似的类型,然后根据行数创建一个 id。有了这个,我们使用该元素作为输入rowwise(),然后我们可以使用c_across()函数。这里的代码(我用过你的df数据):

library(tidyverse)
#Code
df %>% 
  mutate_at(vars(everything()),funs(as.character(.))) %>%
  mutate(id=1:n()) %>%
  rowwise(id) %>%
  mutate(NAs = sum(is.na(c_across(a:d))))

输出:

# A tibble: 4 x 6
# Rowwise:  id
  a     b     c     d        id   NAs
  <chr> <chr> <chr> <chr> <int> <int>
1 tt    2     1     tt        1     0
2 ss    3     2     ss        2     0
3 ss    NA    NA    ss        3     2
4 NA    1     NA    NA        4     3

我们可以避免mutate_at()使用新的函数across()mutate()同源变量:

#Code 2
df %>% 
  mutate(across(a:d,~as.character(.))) %>%
  mutate(id=1:n()) %>%
  rowwise(id) %>%
  mutate(NAs = sum(is.na(c_across(a:d))))

输出:

# A tibble: 4 x 6
# Rowwise:  id
  a     b     c     d        id   NAs
  <chr> <chr> <chr> <chr> <int> <int>
1 tt    2     1     tt        1     0
2 ss    3     2     ss        2     0
3 ss    NA    NA    ss        3     2
4 NA    1     NA    NA        4     3
于 2020-09-18T17:18:28.130 回答
1

一个更快的选择不是使用rowwiseor c_across,而是使用rowSums

library(dplyr)
df %>% 
     mutate(NAs = rowSums(is.na(.)))
#     a  b  c    d NAs
#1   tt  2  1   tt   0
#2   ss  3  2   ss   0
#3   ss NA NA   ss   2
#4 <NA>  1 NA <NA>   3

如果我们想要select某些列,即numeric

df %>%
   mutate(NAs = rowSums(is.na(select(., where(is.numeric)))))
#     a  b  c    d NAs
#1   tt  2  1   tt   0
#2   ss  3  2   ss   0
#3   ss NA NA   ss   2
#4 <NA>  1 NA <NA>   1
于 2020-09-18T19:41:23.500 回答