【问题标题】:Find and Replace first NA in each column without for loops在没有 for 循环的情况下查找并替换每列中的第一个 NA
【发布时间】:2012-06-27 04:19:41
【问题描述】:

尝试在没有 For 循环的情况下执行此操作,但无法解决。

我想用默认值 0.0000001 替换列中的第一个 NA。

我正在进行最后一次观察结转 (LOCF) 插补,但想给它一个默认值。

如果我有以下data.frame:

> Col1        Col2        Col3        Col4
> 1           NA          10          99
> NA          NA          11          99
> 1           NA          12          99
> 1           NA          13          NA

我希望它看起来像这样:

> Col1        Col2        Col3        Col4
> 1           0.0000001   10          99
> 0.0000001   NA          11          99
> 1           NA          12          99
> 1           NA          13          0.0000001 

这是我拥有的代码,但很慢......

#Temporary change for missing first observation
for (u in 1:ncol(data.frame))
{
  for (v in 1:nrow(data.frame)) 
  {
    #Temporary change the first observations in a row to 0.0000001 until it encounters a value that isn't NA
    if(is.na(temp_equity_df_merge2[v,u]))
    {
        temp_equity_df_merge2[v,u]=0.0000001
    }
    else break
  }

我想使用 apply 或一些更快的变体。我正在循环超过 20 列和 100 万行。

提前感谢您的帮助。

【问题讨论】:

  • 既然你提到了LOCF,你可能对library('zoo'); ?na.locf感兴趣
  • 我很感激。这就是我正在使用的,但如果第一个观察结果是空白的,它会忽略它(例如,它不会为第 2 列返回任何内容)。此外,它似乎只在每一列上单独工作,所以当我之后使用 cbind 时,它们的列将具有不同的长度。

标签: performance r for-loop apply na


【解决方案1】:

鉴于您拥有如此庞大的数据集,我会使用data.tableset 来避免复制数据。 apply 两种解决方案都至少复制一次数据。

解决方案涉及一个 for 循环,但是一个高效的循环(执行 length(valid_replace) 事情,每个事情都是瞬时的)

library(data.table)

DT< -as.data.table(dat)

replacing <- lapply(DT, function(x)which(is.na(x))[1])

valid_replace <- Filter(Negate(is.na), replacing)

replace_with <- 0.0001

for(i in seq_along(valid_replace)){
  set(DT, i = valid_replace[i], j = names(valid_replace)[i], value = replace_with)
}

【讨论】:

    【解决方案2】:

    基于 cmets,您可以使用 apply 将函数应用于每一列。该函数将用 0.0000001 替换第一个 NA 并返回一个矩阵。然后可以用na.locf填写剩余的NAs。最后,我将它全部包裹在 data.frame 中,因为您要求使用 data.frame 而不是 matrix

    data.frame(na.locf(apply(dat, 2, function(x) {
        firstNA <- head(which(is.na(x)), 1) #position of first NA
        x[firstNA] <- 0.0000001
        x
    })))
       Col1  Col2 Col3    Col4
    1 1e+00 1e-07   10 9.9e+01
    2 1e-07 1e-07   11 9.9e+01
    3 1e+00 1e-07   12 9.9e+01
    4 1e+00 1e-07   13 1.0e-07
    

    【讨论】:

      【解决方案3】:

      你可以对每一列应用一个函数:

      myfun <- function(x) {
        x[which(is.na(x))[1]] <- 0.1
      
        return(x)
      }
      
      > data.frame(apply(dat, 2, myfun))
         v1  v2 v3   v4
      1 1.0 0.1 10 99.0
      2 0.1  NA 11 99.0
      3 1.0  NA 12 99.0
      4 1.0  NA 13  0.1
      > 
      

      【讨论】:

        猜你喜欢
        • 2015-11-05
        • 1970-01-01
        • 2021-07-12
        • 2019-02-08
        • 2017-09-13
        • 2021-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多