【问题标题】:Get rid of consecutive na in columns of a matirx去掉矩阵列中的连续 na
【发布时间】:2021-05-08 12:31:03
【问题描述】:

我问了同样的问题here,但它已关闭,因为我的帖子与类似问题相关联尽管它们与我的问题无关,也没有解决它。

数据集:

我有一个庞大的数据集保存在一个矩阵中,其中行数超过一百万,有十几列。

矩阵看起来像

data <- matrix(c(1, NA, 2, NA, 1, NA, NA, NA, 1, NA, 3, NA, 5, NA, NA, NA, 8, NA, 5, NA, 7, NA, NA, NA), ncol=3)
> data
     [,1] [,2] [,3]
[1,]    1    1    8
[2,]   NA   NA   NA
[3,]    2    3    5
[4,]   NA   NA   NA
[5,]    1    5    7
[6,]   NA   NA   NA
[7,]   NA   NA   NA
[8,]   NA   NA   NA

因此,如果某列中存在缺失值,那么其他列必然会有同一行的缺失值。

问题:

如果矩阵中所有列的每列有 3 个或更多,我想删除 “有效地” 个连续缺失值。所以我想删除 一列而不是一行中的连续 na。

对于我的问题,我已经看到了解决方案,例如 this one,但它们对于我庞大的数据集来说太慢了。您还有其他可以有效实现目标的建议吗?此外,如果缺失值在行而不是列中是连续的,则我的已关闭问题的建议答案(12)将被删除。

编辑:

按照下面的评论,输出必须是这样的:

         [,1] [,2] [,3]
    [1,]    1    1    8
    [2,]   NA   NA   NA
    [3,]    2    3    5
    [4,]   NA   NA   NA
    [5,]    1    5    7
  

编辑:

> data
         [,1] [,2] [,3] [,4]
    [1,]    1    1    8    NA
    [2,]   NA   NA   NA    NA
    [3,]    2    3    5    NA
    [4,]   NA   NA   NA    NA
    [5,]    1    5    7    NA
    [6,]   NA   NA   NA    NA
    [7,]   NA   NA   NA    NA
    [8,]   NA   NA   NA    NA

预期输出

         [,1] [,2] [,3]
    [1,]    1    1    8
    [2,]   NA   NA   NA
    [3,]    2    3    5
    [4,]   NA   NA   NA
    [5,]    1    5    7
   

【问题讨论】:

    标签: r dataframe matrix data.table na


    【解决方案1】:

    如果是连续的,那么可能是rle可以用

    i1 <- rowSums(is.na(data)) > 0
    # // or just forgot to update here
    i1 <- is.na(data[,1])
    
    data[!inverse.rle(within.list(rle(i1), {
              values[values & lengths < 3] <- FALSE})),]
    

    -输出

    #      [,1] [,2] [,3]
    #[1,]    1    1    8
    #[2,]   NA   NA   NA
    #[3,]    2    3    5
    #[4,]   NA   NA   NA
    #[5,]    1    5    7
    

    更新

    如果我们有一个包含所有NAs 的特定列,那么我们可以先将其删除

    data1 <- data[,colSums(!is.na(data)) != 0]
    

    现在我们将之前的代码应用到选定的列数据上

    i1 <- is.na(data1[,1])
    
    data1[!inverse.rle(within.list(rle(i1), {
          values[values & lengths < 3] <- FALSE})),]
    

    或者我们可以使用data.table 中的rleid(这样会更有效率)

    library(data.table)
    data[as.data.table(data)[, .I[!(.N >=3 & is.na(V1))], 
                 rleid(is.na(V1))]$V1,]
    

    【讨论】:

    • 感谢您的回答。您认为这可能是对数百万数据集最有效的方法吗?
    • @Jean 我在发布答案后看到了预期的更新。最初,它使用apply 循环遍历行。现在,根据您的条件,如果任何一行为 NA,则该行可以全部为 NA,然后选择第一个并使用is.na 检查 NA,或在 is.na 上使用rowSums。在逻辑向量上应用rle 以根据lengths 条件对数据进行子集
    • 感谢您的更新。如果只有一列包含连续缺失值而其他列不包含怎么办?
    • @Jean 在这种情况下,您的预期输出是什么?即您在此处寻找OR 条件还是AND,即所有列都应具有连续的NA,然后将其删除?
    • 是的,你是对的,实际上,所有列都必须在同一行中包含 NA。另一方面,我正在尝试修改您的脚本以包含更一般的情况,即有一个附加列包含连续的 NA,而不管其他列中的值。我将为这种一般情况添加更新。
    【解决方案2】:

    如果某列有缺失值,那么其他列必然会有同一行的缺失值。

    我认为这是非常重要的信息,我们可以利用它并且只使用任何 1 列而不是完整的数据集。试试看:

    vec <- data[, 1]
    data[!with(rle(is.na(vec)), rep(values & lengths >= 3, lengths)), ]
    
    #     [,1] [,2] [,3]
    #[1,]    1    1    8
    #[2,]   NA   NA   NA
    #[3,]    2    3    5
    #[4,]   NA   NA   NA
    #[5,]    1    5    7
    

    【讨论】:

    • 非常感谢,这个答案也归档了目标。
    猜你喜欢
    • 1970-01-01
    • 2020-07-04
    • 1970-01-01
    • 2011-10-12
    • 2020-01-25
    • 1970-01-01
    • 2020-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多