【问题标题】:How to remove rows with inf from a dataframe in R如何从R中的数据框中删除带有inf的行
【发布时间】:2016-04-13 06:24:43
【问题描述】:

我有一个非常大的数据框(df),大约有 35-45 列(变量)和大于 300 的行。一些行包含单个的 NA、NaN、Inf、-Inf 值或多个变量,我用过 na.omit(df) 删除带有 NA 和 NaN 的行,但我无法使用 na.omit 函数删除带有 Inf 和 -Inf 值的行。

在搜索时,我遇到了这个线程 Remove rows with Inf and NaN in R 并使用了修改后的代码 df[is.finite(df)],但它没有删除带有 Inf 和 -Inf 的行并且也给出了这个错误

is.finite(df) 中的错误:未为类型实现默认方法 '列表'

已编辑

即使对应的一列或多列有inf和-inf,也要删除整行

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    要删除带有 +/-Inf 的行,我建议如下:

    df <- df[!is.infinite(rowSums(df)),]
    

    或者,等价的,

    df <- df[is.finite(rowSums(df)),]
    

    第二个选项(带有is.finite() 且不带否定的选项)也会删除包含NA 值的行,以防这尚未完成。

    【讨论】:

    • 这不会处理 NA。 NA+Inf 给出NAis.infinite(NA) 返回FALSE
    • 我以为 OP 说 NA 已经被照顾了...?
    • 猜猜第二种解决方案更健壮,应该更好地处理NA
    • @nicola 感谢您指出!is.infinite()is.finite() 之间的区别。我今天学到了一些东西;-)
    • @jogo 我认为无论如何都必须检查 data.frame 的每个元素。鉴于此,用矢量化函数rowSums()求和应该不会特别费时。
    【解决方案2】:

    根据数据,有几个选项使用dplyr::filter()is.finite()is.infinite() 的范围变体可能有用:

    library(dplyr)
    
    # sample data
    df <- data_frame(a = c(1, 2, 3, NA), b = c(5, Inf, 8, 8), c = c(9, 10, Inf, 11), d = c('a', 'b', 'c', 'd'))
    
    # across all columns:
    df %>% 
      filter_all(all_vars(!is.infinite(.)))
    
    # note that is.finite() does not work with NA or strings:
    df %>% 
      filter_all(all_vars(is.finite(.)))
    
    # checking only numeric columns:
    df %>% 
      filter_if(~is.numeric(.), all_vars(!is.infinite(.)))
    
    # checking only select columns, in this case a through c:
    df %>% 
      filter_at(vars(a:c), all_vars(!is.infinite(.)))
    

    【讨论】:

      【解决方案3】:

      is.finite 适用于 vector 而不是 data.frame 对象。因此,我们可以使用 lapply 循环遍历 data.frame 并仅获取“有限”值。

      lapply(df, function(x) x[is.finite(x)])
      

      如果每列的Inf-Inf 值的数量不同,则上面的代码将有一个list,其中的元素具有不相等的length。因此,最好将其保留为list。如果我们想要一个data.frame,它应该有相同的长度。


      如果我们要删除包含任何 NA 或 Inf/-Inf 值的行

      df[Reduce(`&`, lapply(df, function(x) !is.na(x)  & is.finite(x))),]
      

      或@nicola 的紧凑选项

      df[Reduce(`&`, lapply(df, is.finite)),]
      

      如果我们准备好使用一个包,一个紧凑的选项是NaRV.omit

      library(IDPmisc)
      NaRV.omit(df)
      

      数据

      set.seed(24)
      df <- as.data.frame(matrix(sample(c(1:5, NA, -Inf, Inf), 
                            20*5, replace=TRUE), ncol=5))
      

      【讨论】:

      • 结果输出不在我这样尝试过的数据框中 dim(df) 330 40 df2&lt;-lapply(df, function(x) x[is.finite(x)]) dim(df2) NULL 。我想删除整行,即使其中一列包含 inf,-inf 值
      • 是的,我删除了评论。不要认为!is.na 是必需的,因为is.finite(NA) 返回FALSE
      【解决方案4】:

      要保留没有Inf 的行,我们可以这样做:

      df[apply(df, 1, function(x) all(is.finite(x))), ]
      

      NAs 也被此处理,因为:
      值为 NA 的 rowindex 将删除结果中的这一行。

      带有NaN 的行也不在结果中。

      set.seed(24)
      df <- as.data.frame(matrix(sample(c(0:9, NA, -Inf, Inf, NaN),  20*5, replace=TRUE), ncol=5))
      df2 <- df[apply(df, 1, function(x) all(is.finite(x))), ]
      

      以下是不同is.~-functions 的结果:

      x <- c(42, NA, NaN, Inf)
      is.finite(x)
      # [1]  TRUE FALSE FALSE FALSE
      is.na(x)
      # [1] FALSE  TRUE  TRUE FALSE
      is.nan(x)
      # [1] FALSE FALSE  TRUE FALSE
      

      【讨论】:

        【解决方案5】:

        我遇到了这个问题,以上解决方案都不适合我。我使用以下内容删除了数据框第 15 列和第 16 列中带有 +/-Inf 的行。

        d<-subset(c, c[,15:16]!="-Inf") 
        e<-subset(d, d[,15:16]!="Inf")
        

        【讨论】:

          【解决方案6】:

          我花了一段时间才为 dplyr 1.0.0 解决这个问题,所以我想我会使用 c_across 提供新版本的 @sbha 解决方案,因为 filter_allfilter_if 是被弃用了。

          library(dplyr)
          df <- tibble(a = c(1, 2, 3, NA), b = c(5, Inf, 8, 8), c = c(9, 10, Inf, 11), d = c('a', 'b', 'c', 'd'))
          #       a     b     c d    
          #   <dbl> <dbl> <dbl> <chr>
          # 1     1     5     9 a    
          # 2     2   Inf    10 b    
          # 3     3     8   Inf c    
          # 4    NA     8    11 d 
          
          df %>% 
            rowwise %>% 
            filter(!all(is.infinite(c_across(where(is.numeric)))))
          # # A tibble: 4 x 4
          # # Rowwise: 
          #       a     b     c d    
          #   <dbl> <dbl> <dbl> <chr>
          # 1     1     5     9 a    
          # 2     2   Inf    10 b    
          # 3     3     8   Inf c    
          # 4    NA     8    11 d 
          
          df %>% 
            rowwise %>% 
            filter(!any(is.infinite(c_across(where(is.numeric)))))
          # # A tibble: 2 x 4
          # # Rowwise: 
          #       a     b     c d    
          #   <dbl> <dbl> <dbl> <chr>
          # 1     1     5     9 a    
          # 2    NA     8    11 d 
          
          df %>% 
            rowwise %>% 
            filter(!any(is.infinite(c_across(a:c))))
          
          # # A tibble: 2 x 4
          # # Rowwise: 
          #       a     b     c d    
          #   <dbl> <dbl> <dbl> <chr>
          # 1     1     5     9 a    
          # 2    NA     8    11 d 
          

          老实说,我认为@sbha 的答案更简单!

          【讨论】:

            【解决方案7】:

            我认为自己是编码新手,我无法将上述建议用于我的代码。

            我找到了一种不太复杂的方法来减少 2 行数据框,首先将 Inf 替换为 Na,然后选择包含完整数据的行:

            Df[sapply(Df, is.infinite)] <- NA
            Df<-Df[complete.cases(Df), ]
            

            【讨论】:

              【解决方案8】:
              df[!is.infinite(df$x),]
              

              其中 x 是包含无限值的 df 列。发布的第一个答案取决于行和,但对于我自己的问题,df 有无法添加的列。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2021-05-07
                • 2012-08-24
                • 2011-12-16
                • 2020-08-16
                • 2016-01-16
                • 2022-06-28
                • 1970-01-01
                • 2014-04-12
                相关资源
                最近更新 更多