如何使用dplyr :: c_across()对不同类型的变量进行汇总

4
我有不同类型的变量数据,包括字符型、因子型和数字型,如下所示:
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))

我正在尝试使用dplyr中的c_across函数,以每个观测值计算缺失值数量。 然而,c_across似乎无法组合不同类型的值,正如下面的错误信息所示。

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

错误: summarise() 输入 NAs 有问题。 x 无法组合 a <factor> 和 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高效地按行计算缺失值的数量?

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

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

#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

1
第二个稍微快一点。 - Aureliano Guedes

1

一种更快的选项是不使用 rowwisec_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

如果我们想要选择特定的列,即数值列。
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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接