首页 > 解决方案 > dplyr:在 group_by 之后用零替换 NA,同时在 R 中保留原始 NA

问题描述

我正在创建一个新变量,并且由于 NA 并且因为只有一些人符合分组标准,我最终在我的最终数据集中得到了许多新的 NA。

是数据。

更新示例数据框:

id    age    year   var1
4     KL      2007   15
1     KL      2008   10
2     KL      2008   20
4     AG      2008   NA
3     AG      2008   5    
3     SU      2009   NA
4     SU      2009   NA    
4     LL      2011   NA

数据框细微差别:

  1. age=="KL" & year==2007只有 1 行(有值)
  2. age=="KL" & year==2008有多行(带值)
  3. age=="AG" & year==2008有多行(带有值和 NA)
  4. age=="SU" & year==2009有多行(仅适用于 NA)
  5. age=="LL" & year==2011只有 1 行(带 NA)

示例公式:

df<-df %>%
    group_by(age, year) %>% 
    mutate(new_var1=((var1-mean(var1, na.rm=T))/(1*(sd(var1, na.rm=T)))))

电流输出:

id    age    year   var1    new_var1
4     KL      2007   15      NA
1     KL      2008   10     -0.7071068
2     KL      2008   20      0.7071068
4     AG      2008   NA      NA
3     AG      2008   5       NA
3     SU      2009   NA      NA
4     SU      2009   NA      NA
4     LL      2011   NA      NA

期望的输出:

id    age    year   var1    new_var1
4     KL      2007   15      0
1     KL      2008   10     -0.7071068
2     KL      2008   20      0.7071068
4     AG      2008   NA      NA
3     AG      2008   5       0
3     SU      2009   NA      NA
4     SU      2009   NA      NA
4     LL      2011   NA      NA

如何保留现有的 NA(那些是缺失数据的真实实例),同时强制新 NA 的任何实例(因为该行是唯一的记录)为 0 而不是 NA?

一个dplyr解决方案将不胜感激。

我知道如何用零(例如,mutate(new_var1=ifelse(is.na(new_var1), 0, new_var1)))替换 NA,但这会替换所有 NA,而不仅仅是新的 NA。

标签: rgroup-bydplyr

解决方案


我们可以创建一个条件if/else来检查单个观察值,如果它不是 NA,则返回 0 否则进行计算

library(dplyr)
df %>% 
   group_by(age, year) %>% 
  mutate(var1 = if(n() == 1 && !is.na(var1) | sum(!is.na(var1)) == 1) 0 * var1
  else ((var1-mean(var1, na.rm=TRUE))/(1*(sd(var1, na.rm=TRUE))))) %>%
    ungroup

-输出

# A tibble: 8 x 4
     id age    year   var1
  <int> <chr> <int>  <dbl>
1     4 KL     2007  0    
2     1 KL     2008 -0.707
3     2 KL     2008  0.707
4     4 AG     2008 NA    
5     3 AG     2008  0    
6     3 SU     2009 NA    
7     4 SU     2009 NA    
8     4 LL     2011 NA    

数据

df <- structure(list(id = c(4L, 1L, 2L, 4L, 3L, 3L, 4L, 4L), age = c("KL", 
"KL", "KL", "AG", "AG", "SU", "SU", "LL"), year = c(2007L, 2008L, 
2008L, 2008L, 2008L, 2009L, 2009L, 2011L), var1 = c(15L, 10L, 
20L, NA, 5L, NA, NA, NA)), class = "data.frame", row.names = c(NA, 
-8L))

推荐阅读