使用rowwise()计算数据帧每一行中NA的数量的问题
我在使用 rowwise() 计算每行中的 NA 数量时遇到问题。我的最小例子:
df <- data.frame(Q1 = c(rep(1, 1), rep(NA, 9)),
Q2 = c(rep(2, 2), rep(NA, 8)),
Q3 = c(rep(3, 3), rep(NA, 7))
)
df
Q1 Q2 Q3
1 1 2 3
2 NA 2 3
3 NA NA 3
4 NA NA NA
5 NA NA NA
6 NA NA NA
7 NA NA NA
8 NA NA NA
9 NA NA NA
10 NA NA NA
我想创建一个新列来计算每行中 NA 的数量。我可以通过写作来做到这一点
df$Count_NA <- rowSums(is.na(df))
df
Q1 Q2 Q3 Count_NA
1 1 2 3 0
2 NA 2 3 1
3 NA NA 3 2
4 NA NA NA 3
5 NA NA NA 3
6 NA NA NA 3
7 NA NA NA 3
8 NA NA NA 3
9 NA NA NA 3
10 NA NA NA 3
但是,如果我尝试使用 rowwise() 通过 dplyr 执行此操作,则会得到错误的答案 - Count_NA 列在每一行中具有相同的数字:
df %>%
rowwise() %>%
mutate(Count_NA = sum(is.na(.)))
# A tibble: 10 x 4
# Rowwise:
Q1 Q2 Q3 Count_NA
<dbl> <dbl> <dbl> <int>
1 1 2 3 24
2 NA 2 3 24
3 NA NA 3 24
4 NA NA NA 24
5 NA NA NA 24
6 NA NA NA 24
7 NA NA NA 24
8 NA NA NA 24
9 NA NA NA 24
10 NA NA NA 24
我做错了什么,我该如何解决?
提前谢谢了
托马斯·菲利普斯
回答
使用cur_data()而不是点。 .[cur_group_id(), ], c(Q1, Q2, Q3),across()或c_across()(或c_across根据其他答案的论点)也可以。
请注意,最好在ungroup之后使用,否则它会保留 rowwise 的内存,稍后您可能会得到意想不到的结果。
df %>%
rowwise() %>%
mutate(Count_NA = sum(is.na(cur_data()))) %>%
ungroup
给予:
# A tibble: 10 x 4
Q1 Q2 Q3 Count_NA
<dbl> <dbl> <dbl> <int>
1 1 2 3 0
2 NA 2 3 1
3 NA NA 3 2
4 NA NA NA 3
5 NA NA NA 3
6 NA NA NA 3
7 NA NA NA 3
8 NA NA NA 3
9 NA NA NA 3
10 NA NA NA 3
回答
一个问题是.这里解决了整个框架,而不仅仅是整行。另一种 dplyr 方法,使用c_across:
df %>%
rowwise() %>%
mutate(a=sum(is.na(c_across(everything()))))
# # A tibble: 10 x 4
# # Rowwise:
# Q1 Q2 Q3 a
# <dbl> <dbl> <dbl> <int>
# 1 1 2 3 0
# 2 NA 2 3 1
# 3 NA NA 3 2
# 4 NA NA NA 3
# 5 NA NA NA 3
# 6 NA NA NA 3
# 7 NA NA NA 3
# 8 NA NA NA 3
# 9 NA NA NA 3
# 10 NA NA NA 3
我可以看到使用它的最大区别cur_data()在于它c_across允许更直接地进行变量选择,如c_across(starts_with("Q")). 当然,一个人总是可以select(cur_data(),...),所以这是一个弱论点。
回答
基本答案
df$Count_NA <- apply(df, 1, function(x) sum(is.na(x)))
df
Q1 Q2 Q3 Count_NA
1 1 2 3 0
2 NA 2 3 1
3 NA NA 3 2
4 NA NA NA 3
5 NA NA NA 3
6 NA NA NA 3
7 NA NA NA 3
8 NA NA NA 3
9 NA NA NA 3
10 NA NA NA 3
所以可以集成到dplyr管道中
df %>% mutate(count_NA = apply(., 1, function(x) sum(is.na(x))))
Q1 Q2 Q3 count_NA
1 1 2 3 0
2 NA 2 3 1
3 NA NA 3 2
4 NA NA NA 3
5 NA NA NA 3
6 NA NA NA 3
7 NA NA NA 3
8 NA NA NA 3
9 NA NA NA 3
10 NA NA NA 3
回答
rowSums直接使用mutate而无需rowwise:
df %>% mutate(count_NA = rowSums(is.na(.)))
Q1 Q2 Q3 count_NA
1 1 2 3 0
2 NA 2 3 1
3 NA NA 3 2
4 NA NA NA 3
5 NA NA NA 3
6 NA NA NA 3
7 NA NA NA 3
8 NA NA NA 3
9 NA NA NA 3
10 NA NA NA 3
请注意,您的初始解决方案是迄今为止最快的解决方案:
microbenchmark::microbenchmark(
df$Count_NA <- rowSums(is.na(df)),
df$Count_NA <- apply(df, 1, function(x) sum(is.na(x))),
df %>% mutate(count_NA = rowSums(is.na(.))),
df %>%
mutate(Count_NA = purrr::pmap(., ~ sum(is.na(c(...))))),
df %>%
rowwise() %>%
mutate(a=sum(is.na(c_across(everything())))),
df %>%
rowwise() %>%
mutate(Count_NA = sum(is.na(cur_data()))) %>%
ungroup
)
Unit: microseconds
expr min lq
df$Count_NA <- rowSums(is.na(df)) 39.8 64.30
df$Count_NA <- apply(df, 1, function(x) sum(is.na(x))) 1661.6 1868.40
df %>% mutate(count_NA = rowSums(is.na(.))) 1181.7 1572.80
df %>% mutate(Count_NA = purrr::pmap(., ~sum(is.na(c(...))))) 4749.9 5190.35
df %>% rowwise() %>% mutate(a = sum(is.na(c_across(everything())))) 29124.1 31148.50
df %>% rowwise() %>% mutate(Count_NA = sum(is.na(cur_data()))) %>% ungroup 70473.0 73659.70
mean median uq max neval cld
79.033 76.25 88.75 174.0 100 a
2082.960 1966.50 2075.75 8777.3 100 b
1722.178 1676.20 1791.60 3112.9 100 b
5726.549 5396.40 5745.25 28592.1 100 c
33567.825 31983.05 33637.00 54676.9 100 d
77902.342 76492.85 81199.15 98942.1 100 e
Unit: microseconds
expr min lq
df$Count_NA <- rowSums(is.na(df)) 38.2 44.95
df$Count_NA <- apply(df, 1, function(x) sum(is.na(x))) 1584.8 1765.30
df %>% mutate(count_NA = rowSums(is.na(.))) 1247.9 1496.95
df %>% mutate(Count_NA = purrr::pmap(., ~sum(is.na(c(...))))) 4614.0 5110.50
df %>% rowwise() %>% mutate(Count_NA = sum(is.na(cur_data()))) %>% ungroup 67413.5 70865.45
mean median uq max neval cld
71.159 65.85 84.40 162.2 100 a
1967.629 1894.45 2093.30 3436.6 100 ab
1814.193 1666.25 1895.35 9031.0 100 a
5796.483 5380.70 5665.10 15309.7 100 b
78309.807 75275.30 79776.40 286964.3 100 c