dplyr:在group_by之后用零替换NAs,同时将原始NAs保留在R中

dplyr:在group_by之后用零替换NAs,同时将原始NAs保留在R中,r,dplyr,group-by,mutate,R,Dplyr,Group By,Mutate,我正在创建一个新变量,因为NAs,并且因为只有一些人符合分组标准,我最终的数据集中有许多新的NAs 这是数据 更新的示例数据帧: 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

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

这是数据

更新的示例数据帧:

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
数据帧细微差别:

  • age==“KL”&year==2007
    只有一行(带值)
  • age==“KL”&year==2008
    有多行(带值)
  • age==“AG”&year==2008
    有多行(带值和NAs)
  • age==“SU”&year==2009
    有多行(仅限NAs)
  • age==“LL”&year==2011
    只有一行(带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      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
    
    在强制任何新NAs实例(因为行是唯一的记录)为0而不是NA时,如何保留现有NAs(这些是丢失数据的真实实例)?

    非常感谢
    dplyr
    解决方案


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

    我们可以使用
    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    
    
    #一个tible:8 x 4
    id年龄年变量1
    14吉隆坡2007 0
    21吉隆坡2008-0.707
    3.2吉隆坡2008 0.707
    4 4 AG 2008 NA
    5 3 AG 2008 0
    6 3苏2009 NA
    7 4苏2009 NA
    2011年4月8日北美
    
    数据
    df选项可以是:

    df%
    按年龄、年份划分的组别%>%
    变异(new_var1=ifelse(is.nan(scale(var1)),0,scale(var1)))%>%
    解组()
    #>#A tibble:8 x 5
    #>id年龄年变量1新变量1[,1]
    #>              
    #>14吉隆坡2007 15 0
    #>2 1吉隆坡2008 10-0.707
    #>3 2吉隆坡2008 20 0.707
    #>4 4 AG 2008 NA
    #>5 3 AG 2008 5 0
    #>6 3苏2009娜娜娜
    #>7 4苏2009纳纳
    #>2011年4月8日不适用
    库(数据表)
    setDT(df)[,new_var1:=ifelse(is.nan(scale(var1)),0,scale(var1)),by=list(age,year)][]
    #>id年龄年变量1新变量1
    #>1:4 KL 2007 150.0000000
    #>2:1吉隆坡2008 10-0.7071068
    #>3:2吉隆坡2008 20 0.7071068
    #>4:4 AG 2008 NA NA
    #>5:3 AG 2008 500.0000000
    #>6:3苏2009娜娜娜
    #>7:4苏2009娜娜娜
    #>8:4 LL 2011不适用
    

    由(v2.0.0)

    于2021-05-21创建。由于某种原因,当我尝试应用您的解决方案时,它会为整个列返回NaN。你能帮我解决一下为什么它对你的答案有效,但对我来说不行吗?@BlunderingColomist这是基于你展示的同一个例子吗?在您的原始数据中,我猜测有多个组有一个以上的观察,并且所有组都是NA,这导致
    NaN
    ,而您使用
    mean
    进行计算,啊,我认为可能是这样。我试图用上面一个简明的例子来避免让它压倒一切,但我认为我遗漏了一些重要的细微差别?@BlunderingColomist我在这里没有包括这个条件。此外,在某些情况下,有一个单独的非NA元素,sd可以返回NAI think,这在我的原始数据集中更为常见(一个单独的非NA元素,由于
    sd()
    函数,它最终会给出一个NA)。是否有可能修改您的答案以适应这些条件?(我很抱歉没有提出更好的问题)。我将更新我的示例数据集以尝试包含这些内容。id 4的最后一行的输出是什么?就像noob一样,我没有指定年龄的编码(它是分类的,不是数字的)。我还将真实数据添加到了问题中。这并不重要,因为我们正在进行分组,并且值是根据numericHmmm计算的。我这方面一定很傻。我不想再浪费你的时间了,谢谢你的帮助!
    # 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))