如何从R中的数据框中删除带有inf的行

时间:2016-04-13 06:24:44

标签: r dataframe

我有一个非常大的数据帧( 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)中的错误:未对类型实现默认方法   '列表'

EDITED

删除整行,即使相应的一列或多列都有inf和-inf

8 个答案:

答案 0 :(得分:21)

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

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

或等同地

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

第二个选项(具有is.finite()且没有否定的选项)也会删除包含NA值的行,以防尚未执行此操作。

答案 1 :(得分:8)

is.finite适用于vector而非data.frame对象。因此,我们可以使用data.frame遍历lapply并仅获取有限的&#39;值。

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))

答案 2 :(得分:4)

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

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

由于以下原因,NA也由此处理:
值为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.~ - 函数的结果:

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

答案 3 :(得分: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(.)))

答案 4 :(得分:1)

我认为自己是编码新手,无法获得上述建议来处理我的代码。

我找到了一种不太复杂的方法来减少 2 行数据帧,首先用 Na 替换 Inf,然后选择具有完整数据的行:

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

答案 5 :(得分:1)

df[!is.infinite(df$x),]

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

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

我花了一段时间为 dplyr 1.0.0 进行了研究,所以我认为自c_across起,我将使用filter_all提出新版本的@sbha解决方案, filter_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的答案更简单!