【问题标题】:How to fill NA in R for quasi-same row?如何在R中填写NA以获得准相同的行?
【发布时间】:2019-05-29 06:26:45
【问题描述】:

我正在寻找一种在duplicated() 行中填充NA 的方法。有完全相同的行,一次有一个 NA,所以我决定用完整行的值填充这一行,但我不知道如何处理它。

使用duplicated() 函数,我可以有一个这样的数据框:

 df <- data.frame(
   Year = rnorm(5), 
   hour = rnorm(5), 
   LOT = rnorm(5), 
   S123_AA = c('ABF4576','ABF4576','ABF4576','ABF4576','ABF4576'), 
   S135_AA = c('ABF5403',NA,'ABF5403','ABF5403','ABF5403'), 
   S13_BB = c('BF50343','BF50343','BF50343','BF50343',NA),  
   S1763_BB = c('AA3489','AA3489','AA3489','AA3489','AA3489'), 
   S173_BB = c('BQA0478','BQA0478','BQA0478','BQA0478','BQA0478'),
   S234543 = c('AD4352','AD4352','AD4352','AD4352','AD4352'),
   S1265UU5 = c('AZERTY', 'AZERTY', 'AZERTY', 'AZERTY','AZERTY')
 )

这些行是相似的,那么我怎么能通过前面的原始值(不是 NA)来感受 NA 呢?没有complete.cases()rows。

【问题讨论】:

    标签: r duplicates na


    【解决方案1】:

    您可以遍历数据并找到第一个无 NA 值并将 NA 值替换为该值

    # Loop through the data
    for(c in 1:ncol(df)) {
        vals <- df[,c]
        noneNA <- vals[!is.na(vals)][1]
        vals[is.na(vals)] <- noneNA
        df[,c] <- vals
    }
    

    或者,您也可以逐个查看数据元素,并使用嵌套的 for 循环从相关单元格的上方或下方获取无 NA 值。

    for(c in 1:ncol(df)) {
        for(r in 1:nrow(df)) {
            if (is.na(df[r,c])) {
                nearVals <- df[c(r-1, r+1),c]
                noneNA <- nearVals[!is.na(nearVals)][1]
                df[r,c] <- noneNA
            }
        }
    }
    

    【讨论】:

    • 感谢您的回答,我的问题是没有complete.cases() 行。该值可以取自前一行或后三行
    • 感谢您的帮助,我只是更改了(r-1, r+1) 部分。您知道在完整数据框中“替换”此子集的任何功能吗?在这里它只是相似的行,我想将它重新整合到完整的 df 中,给定一行 5 个或更多键。
    • 这里的代码循环遍历整个数据集。语句 df[r,c]
    • 我的 df 是另一个完整的子集。这里只是类似的行。
    • 在这种情况下,这听起来像是您的示例数据,它不能完全代表您要解决的问题。你有问题中的例子真是太棒了。有什么方法可以调整它以包含不同的行,就像在完整数据集中一样?
    【解决方案2】:

    阅读您的问题让我想到了数据框的imputation problem

    换句话说,您需要用某种值填充 NA,以便能够“保存”数据框中的记录。最简单的方法是通过搜索均值(处理基值时)或模式(处理分类值时)来选择特定列的值[您也可以执行回归,但我想这是一种更复杂的方法] .

    在这种情况下,我们可以选择模式替换,因为属性是分类的。通过运行您的代码,我们获得了数据框df

             Year       hour         LOT S123_AA S135_AA  S13_BB S1763_BB S173_BB S234543 S1265UU5
    1 -0.32837526  0.7930541 -1.10954824 ABF4576 ABF5403 BF50343   AA3489 BQA0478  AD4352   AZERTY
    2  0.55379245 -0.7320060 -0.95088434 ABF4576    <NA> BF50343   AA3489 BQA0478  AD4352   AZERTY
    3  0.36442118  0.9920967 -0.07345038 ABF4576 ABF5403 BF50343   AA3489 BQA0478  AD4352   AZERTY
    4 -0.02546781 -0.1127828 -1.78241434 ABF4576 ABF5403 BF50343   AA3489 BQA0478  AD4352   AZERTY
    5  1.92550340 -1.0531371  0.88318695 ABF4576 ABF5403    <NA>   AA3489 BQA0478  AD4352   AZERTY
    

    然后我们可以创建一个函数来计算特定列的模式:

    getmode <- function(v) {
    uniqv <- unique(v)
    uniqv[which.max(tabulate(match(v, uniqv)))]
    }
    

    然后用它来填充缺失的值。下面的代码用于估算列 S135_AA 的缺失值(我创建了一个名为 workdf 的新数据框):

    workdf <- df
    workdf[is.na(workdf$S135_AA),c('S135_AA')] <- getmode(workdf[,'S135_AA'])
    

    这是输出,您可以看到列S135_AA NAs 采用了该列中重复次数最多的值:

             Year       hour         LOT S123_AA S135_AA  S13_BB S1763_BB S173_BB S234543 S1265UU5
    1 -0.32837526  0.7930541 -1.10954824 ABF4576 ABF5403 BF50343   AA3489 BQA0478  AD4352   AZERTY
    2  0.55379245 -0.7320060 -0.95088434 ABF4576 ABF5403 BF50343   AA3489 BQA0478  AD4352   AZERTY
    3  0.36442118  0.9920967 -0.07345038 ABF4576 ABF5403 BF50343   AA3489 BQA0478  AD4352   AZERTY
    4 -0.02546781 -0.1127828 -1.78241434 ABF4576 ABF5403 BF50343   AA3489 BQA0478  AD4352   AZERTY
    5  1.92550340 -1.0531371  0.88318695 ABF4576 ABF5403    <NA>   AA3489 BQA0478  AD4352   AZERTY
    

    如果您的目标是数据清理,我想您应该使用插补方法来处理它。

    【讨论】:

    • 感谢您的明确回答。只是一个问题,这是一个所有行都相似的子集,但是无论如何要在完整的 DF 上处理 NA ?哪里有几组不同的“相同”原料?该模式如何工作?
    • 例如:您正在考虑 S135_AA 包含不同值而不仅仅是 "ABF5403" 的情况?在这种情况下,模式将采用最频繁的值并对其进行估算。事实是,从您的起始数据框中您有 NA,因此,如果您想保留一个特定的数据点,您必须选择一个值来归因于它们,但只能估算一个值。否则,您将不得不删除该数据点。
    • 好的,我知道了,我会去missForest()看看它是否有帮助
    • 您还可以查看kNN 来估算缺失值,如果您希望获得漂亮的报告可视化图,请访问vis_miss
    【解决方案3】:

    您可以执行以下操作:

    library(zoo)
    
    # get cols with missing values
    na_cols <- names(df)[colSums(is.na(df)) > 0]
    
    # fill the missing value backwards
    for (i in na_cols){
        df[[i]] <- na.locf(df[[i]])
    }
    

    【讨论】:

      猜你喜欢
      • 2018-06-04
      • 2019-03-31
      • 2021-11-30
      • 1970-01-01
      • 2022-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多