【问题标题】:Replacing NAs in R dataframe with zeros conditional on an id以 id 为条件用零替换 R 数据帧中的 NA
【发布时间】:2014-04-10 07:39:51
【问题描述】:

我有一个具有多个 NA 的 data.frame。我已经知道,如果某列对于某些公司有一些零值,那么这些 NA 也是零。用零替换那些和只有那些 NA 的好方法是什么。

一个例子:

我想改造一下

  FIRMID    VAR1     VAR2        
  FIRM1     0        1
  FIRM1     NA       NA
  FIRM2     1        0
  FIRM2     NA       NA

到这里

  FIRMID    VAR1     VAR2        
  FIRM1     0        1
  FIRM1     0        NA
  FIRM2     1        0
  FIRM2     NA       0

编辑:变量的数量可能很大,因此我想找到一种方法将其巧妙地同时应用于所有变量,而无需手动输入每个变量名称。

【问题讨论】:

  • VAR1VAR2 的值是否总是:0,1,NA?
  • 它们是 NA、零和非零。所以 1 只是一个代表非零的例子。

标签: r dataframe na


【解决方案1】:

这是另一个ddply 替代方法,您不必指定应应用该函数的变量名称。通过使用numcolwise,该函数对所有数值列进行操作。

library(plyr)

myfun <- function(x){
  x[is.na(x) & (sum(!is.na(x) & x == 0) > 0)] <- 0
  x}

ddply(df, .(FIRMID), numcolwise(myfun))

#   FIRMID VAR1 VAR2
# 1  FIRM1    0    1
# 2  FIRM1    0   NA
# 3  FIRM2    1    0
# 4  FIRM2   NA    0

或者在base R 中,我假设第一列包含分组变量(dat[ , -1])。你当然可以用名字来引用它。

df2 <- do.call(rbind, by(df, df[ , "FIRMID"], function(dat){
  sapply(dat[ , -1], function(x){
    myfun(x)
  })
}))

data.frame(FIRMID = df$FIRMID, df2)

#   FIRMID VAR1 VAR2
# 1  FIRM1    0    1
# 2  FIRM1    0   NA
# 3  FIRM2    1    0
# 4  FIRM2   NA    0

Update 'myfun' 可以写得更简单。感谢@Arun 的建议!

myfun <- function(x){
  x[is.na(x) & any(x == 0)] <- 0
  x}

【讨论】:

    【解决方案2】:

    如果你没有只有整数,你可能需要调整它来比较浮点数:

    DF <- read.table(text="FIRMID    VAR1     VAR2        
    FIRM1     0        1
    FIRM1     NA       NA
    FIRM2     1        0
    FIRM2     NA       NA", header=TRUE)
    
    na_replace <- function(x) {
      if (any(na.omit(x)==0L)) x[is.na(x)] <- 0L
      x
    }
    
    library(plyr)
    ddply(DF, .(FIRMID), transform, 
          VAR1=na_replace(VAR1),
          VAR2=na_replace(VAR2))
    
    #  FIRMID VAR1 VAR2
    #1  FIRM1    0    1
    #2  FIRM1    0   NA
    #3  FIRM2    1    0
    #4  FIRM2   NA    0
    

    【讨论】:

      【解决方案3】:

      您可以在此处使用 ddply。但如果 data.frame 非常大,效率会非常低。如果没有,那你可以试试:

      your.data.frame<-ddply(your.data.frame,~FIRMID,function(x){
      if ( any(x[!is.na(x$VAR1),"VAR1"]==0)){x[is.na(x$VAR1),"VAR1"]<-0}
      if ( any(x[!is.na(x$VAR2),"VAR2"]==0)){x[is.na(x$VAR2),"VAR2"]<-0}
      x})
      

      但很不优雅

      编辑:我之前的代码不起作用,所以我修复了它:)

      【讨论】:

        猜你喜欢
        • 2017-01-30
        • 2018-12-11
        • 1970-01-01
        • 1970-01-01
        • 2021-06-27
        • 1970-01-01
        • 1970-01-01
        • 2021-11-05
        • 1970-01-01
        相关资源
        最近更新 更多