使用 dplyr 在缺失值中创建行式条件
Using dplyr to make row wise conditions amidst missing values
我有一个大型数据集,包含个人、他们的年龄以及 5 项测试的分数和一些缺失数据。数据集如下所示:
id<-c(1, 2, 3, 4, 5, 6, 7)
age<-c(25, 43, 55, 12, 15, 67, 71)
score1<-c(1, 2, 1, 2, 1, 2, 2)
score2<-c(5, NA, NA, 5, 6, 7, 5)
score3<-c(NA, NA, NA, NA, 6, 7, 6)
score4<-c( 5, NA, NA, NA, NA, 6, NA)
score5<-c(5, 5, 4, 4, 5, 5, NA)
df<-data.frame(id, age, score1, score2, score3, score4, score5)
df
id age score1 score2 score3 score4 score5
1 1 25 1 5 NA 5 5
2 2 43 2 NA NA NA 5
3 3 55 1 NA NA NA 4
4 4 12 2 5 NA NA 4
5 5 15 1 6 6 NA 5
6 6 67 2 7 7 6 5
7 7 71 2 5 6 NA NA
对于分数 2-5,我想创建一个 Missing
条件,如果每个 id
在分数 2-5 中的缺失数据 (NA) 超过 30%,则 Missing
=是 否则 Missing
=否
所需的输出应如下所示:
id age score1 score2 score3 score4 score5 missing
1 1 25 1 5 NA 5 5 no
2 2 43 2 NA NA NA 5 yes
3 3 55 1 NA NA NA 4 yes
4 4 12 2 5 NA NA 4 yes
5 5 15 1 6 6 NA 5 no
6 6 67 2 7 7 6 5 no
7 7 71 2 5 6 NA NA yes
在 dplyr 中创建按行条件的最佳方法是什么?我尝试在 df %>% rowwise() %>% missing=ifelse(sum(is.na(.x))/length(.x)* 100 >=30), "yes", "no")
中使用 dplyr::mutate
和 ifelse
,但我认为这是错误的并且似乎不起作用。
df %>%
rowwise %>%
mutate(missing=ifelse(mean(is.na(across(score2:score5)))>0.3,'yes','no')) %>%
ungroup
输出;
id age score1 score2 score3 score4 score5 missing
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
1 1 25 1 5 NA 5 5 no
2 2 43 2 NA NA NA 5 yes
3 3 55 1 NA NA NA 4 yes
4 4 12 2 5 NA NA 4 yes
5 5 15 1 6 6 NA 5 no
6 6 67 2 7 7 6 5 no
7 7 71 2 5 6 NA NA yes
我们可以使用rowMeans(condition)
。我建议您在这里使用 num_range
选择,它非常适合您的列选择语句。
df %>% mutate(missing=ifelse(rowMeans(across(num_range('score', 2:5), is.na))>0.3, 'yes', 'no'))
id age score1 score2 score3 score4 score5 missing
1 1 25 1 5 NA 5 5 no
2 2 43 2 NA NA NA 5 yes
3 3 55 1 NA NA NA 4 yes
4 4 12 2 5 NA NA 4 yes
5 5 15 1 6 6 NA 5 no
6 6 67 2 7 7 6 5 no
7 7 71 2 5 6 NA NA yes
(我的建议与 GuedesBF 提供的几乎相同,但是当我点击“Post”时我没有看到它。为了基准和讨论。)
不使用 rowwise
的替代方案。
df %>%
mutate(Missing = rowMeans(is.na(subset(., select=score2:score5))) > 0.3)
# id age score1 score2 score3 score4 score5 Missing
# 1 1 25 1 5 NA 5 5 FALSE
# 2 2 43 2 NA NA NA 5 TRUE
# 3 3 55 1 NA NA NA 4 TRUE
# 4 4 12 2 5 NA NA 4 TRUE
# 5 5 15 1 6 6 NA 5 FALSE
# 6 6 67 2 7 7 6 5 FALSE
# 7 7 71 2 5 6 NA NA TRUE
优点是性能。一般来说,按行操作会比较慢,如果您的数据显着大,那么这可能是个问题。
bench::mark(
rowwise = df %>% rowwise() %>% mutate(missing=mean(is.na(across(score2:score5)))>0.3) %>% ungroup(),
rowMeans = df %>% mutate(Missing = rowMeans(is.na(subset(., select=score2:score5))) > 0.3),
guedes = df %>% mutate(missing=rowMeans(across(num_range('score', 2:5), is.na))>0.3),
check=FALSE)
# # A tibble: 3 x 13
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time result memory time gc
# <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm> <list> <list> <list> <list>
# 1 rowwise 5.91ms 6.61ms 146. 10.05KB 0 74 0 507ms <NULL> <Rprofmem[,3] [21 x 3]> <bch:tm [74]> <tibble [74 x 3]>
# 2 rowMeans 1.7ms 2ms 439. 1.64KB 2.30 191 1 435ms <NULL> <Rprofmem[,3] [4 x 3]> <bch:tm [192]> <tibble [192 x 3]>
# 3 guedes 2.97ms 3.44ms 272. 13.24KB 0 137 0 503ms <NULL> <Rprofmem[,3] [21 x 3]> <bch:tm [137]> <tibble [137 x 3]>
其中 rowMeans
方法大约是速度的 3 倍。
我有一个大型数据集,包含个人、他们的年龄以及 5 项测试的分数和一些缺失数据。数据集如下所示:
id<-c(1, 2, 3, 4, 5, 6, 7)
age<-c(25, 43, 55, 12, 15, 67, 71)
score1<-c(1, 2, 1, 2, 1, 2, 2)
score2<-c(5, NA, NA, 5, 6, 7, 5)
score3<-c(NA, NA, NA, NA, 6, 7, 6)
score4<-c( 5, NA, NA, NA, NA, 6, NA)
score5<-c(5, 5, 4, 4, 5, 5, NA)
df<-data.frame(id, age, score1, score2, score3, score4, score5)
df
id age score1 score2 score3 score4 score5
1 1 25 1 5 NA 5 5
2 2 43 2 NA NA NA 5
3 3 55 1 NA NA NA 4
4 4 12 2 5 NA NA 4
5 5 15 1 6 6 NA 5
6 6 67 2 7 7 6 5
7 7 71 2 5 6 NA NA
对于分数 2-5,我想创建一个 Missing
条件,如果每个 id
在分数 2-5 中的缺失数据 (NA) 超过 30%,则 Missing
=是 否则 Missing
=否
所需的输出应如下所示:
id age score1 score2 score3 score4 score5 missing
1 1 25 1 5 NA 5 5 no
2 2 43 2 NA NA NA 5 yes
3 3 55 1 NA NA NA 4 yes
4 4 12 2 5 NA NA 4 yes
5 5 15 1 6 6 NA 5 no
6 6 67 2 7 7 6 5 no
7 7 71 2 5 6 NA NA yes
在 dplyr 中创建按行条件的最佳方法是什么?我尝试在 df %>% rowwise() %>% missing=ifelse(sum(is.na(.x))/length(.x)* 100 >=30), "yes", "no")
中使用 dplyr::mutate
和 ifelse
,但我认为这是错误的并且似乎不起作用。
df %>%
rowwise %>%
mutate(missing=ifelse(mean(is.na(across(score2:score5)))>0.3,'yes','no')) %>%
ungroup
输出;
id age score1 score2 score3 score4 score5 missing
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
1 1 25 1 5 NA 5 5 no
2 2 43 2 NA NA NA 5 yes
3 3 55 1 NA NA NA 4 yes
4 4 12 2 5 NA NA 4 yes
5 5 15 1 6 6 NA 5 no
6 6 67 2 7 7 6 5 no
7 7 71 2 5 6 NA NA yes
我们可以使用rowMeans(condition)
。我建议您在这里使用 num_range
选择,它非常适合您的列选择语句。
df %>% mutate(missing=ifelse(rowMeans(across(num_range('score', 2:5), is.na))>0.3, 'yes', 'no'))
id age score1 score2 score3 score4 score5 missing
1 1 25 1 5 NA 5 5 no
2 2 43 2 NA NA NA 5 yes
3 3 55 1 NA NA NA 4 yes
4 4 12 2 5 NA NA 4 yes
5 5 15 1 6 6 NA 5 no
6 6 67 2 7 7 6 5 no
7 7 71 2 5 6 NA NA yes
(我的建议与 GuedesBF 提供的几乎相同,但是当我点击“Post”时我没有看到它。为了基准和讨论。)
不使用 rowwise
的替代方案。
df %>%
mutate(Missing = rowMeans(is.na(subset(., select=score2:score5))) > 0.3)
# id age score1 score2 score3 score4 score5 Missing
# 1 1 25 1 5 NA 5 5 FALSE
# 2 2 43 2 NA NA NA 5 TRUE
# 3 3 55 1 NA NA NA 4 TRUE
# 4 4 12 2 5 NA NA 4 TRUE
# 5 5 15 1 6 6 NA 5 FALSE
# 6 6 67 2 7 7 6 5 FALSE
# 7 7 71 2 5 6 NA NA TRUE
优点是性能。一般来说,按行操作会比较慢,如果您的数据显着大,那么这可能是个问题。
bench::mark(
rowwise = df %>% rowwise() %>% mutate(missing=mean(is.na(across(score2:score5)))>0.3) %>% ungroup(),
rowMeans = df %>% mutate(Missing = rowMeans(is.na(subset(., select=score2:score5))) > 0.3),
guedes = df %>% mutate(missing=rowMeans(across(num_range('score', 2:5), is.na))>0.3),
check=FALSE)
# # A tibble: 3 x 13
# expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time result memory time gc
# <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm> <list> <list> <list> <list>
# 1 rowwise 5.91ms 6.61ms 146. 10.05KB 0 74 0 507ms <NULL> <Rprofmem[,3] [21 x 3]> <bch:tm [74]> <tibble [74 x 3]>
# 2 rowMeans 1.7ms 2ms 439. 1.64KB 2.30 191 1 435ms <NULL> <Rprofmem[,3] [4 x 3]> <bch:tm [192]> <tibble [192 x 3]>
# 3 guedes 2.97ms 3.44ms 272. 13.24KB 0 137 0 503ms <NULL> <Rprofmem[,3] [21 x 3]> <bch:tm [137]> <tibble [137 x 3]>
其中 rowMeans
方法大约是速度的 3 倍。