选择带有无穷大值(Inf 或 -Inf)的行

3

如何从至少有一个无穷值(Inf-Inf)的数据框中选择行?

以下是一个示例数据框:

my_data <- data.frame(column1 = c(Inf, 5, 3,4,5), 
                      column2 = c(1, Inf, -Inf, NA, 33))

我尝试过:

my_data[rowSums(is.infinite(my_data)) > 0, ]

但是出现了错误:

Error in is.infinite(my_data) : default method not implemented for type 'list'

这很令人惊讶,因为 is.na() 的等效方法可以正常工作:

my_data[rowSums(is.na(my_data)) > 0, ]

我找到了一些将Inf值更改为NA的方法,但这不是我想要的,我只想显示所有包含Inf-Inf的行,而不是用NA替换它们。

编辑:如果有一种方法可以在一个具有多个列的数据框中执行此操作,而无需逐个键入每个列,则最理想。

任何帮助都将不胜感激!


1
关于“Which is surprising”,请参阅有关参数x?is.infinite:“默认方法处理原子向量”。然后参见相应的文本?is.na - Henrik
3个回答

3

看起来 is.infinite 无法应用在数据框上。一个替代方法是使用 sapply:

my_data[rowSums(sapply(my_data, is.infinite)) > 0, ]

#   column1 column2
# 1     Inf       1
# 2       5     Inf
# 3       3    -Inf

使用 dplyr,您可以使用if_anyif_allis.infinite应用于一组列,并将结果组合成单个逻辑向量。

library(dplyr)

my_data %>%
  filter(if_any(where(is.numeric), is.infinite))

2
或者 my_data[is.infinite(rowSums(my_data)), ] - Henrik
1
非常感谢Darren Tsai,您的答案很有效,即使数据框中有非数字列!Henrik,感谢您的回答,但仅当整个数据框为数字时才有效。 “在rowSums(my_data)中出错:'x'必须是数字” - juliefoxsteven
谢谢您澄清,@juliefoxsteven。我以为您的玩具数据代表了您的真实数据。 - Henrik

1

类似这样的东西应该可以工作

library(tidyverse)

my_data <- data.frame(column1 = c(Inf, 5, 3,4,5), 
                      column2 = c(1, Inf, -Inf, NA, 33))


my_data
#   column1 column2
# 1     Inf       1
# 2       5     Inf
# 3       3    -Inf
# 4       4      NA
# 5       5      33

my_data %>% 
  filter(is.infinite(column1) | is.infinite(column2))
#   column1 column2
# 1     Inf       1
# 2       5     Inf
# 3       3    -Inf


如果你需要给太多的列起名字,你可以使用if_any()(感谢@RuiBarradas),例如:
# Across all columns
my_data %>% 
  filter(if_any(everything(), is.infinite)) 

# Across a range of columns
my_data %>% 
  filter(if_any(column1:column2, is.infinite)) 

嗨stevec,感谢回复。对于我的简单示例确实有效。但是,我的实际数据集有100多列,抱歉我应该提到了,将编辑我的原始帖子。 - juliefoxsteven
2
@juliefoxsteven my_data %>% filter(if_any(everything(), is.infinite))is.infinitee 应用于所有列。如果要将它应用于某些列,请将 everything() 更改为列选择。 - Rui Barradas
@RuiBarradas 很棒。我尝试使用 across() 但是没能成功。你知道有什么方法可以实现吗? - stevec
1
@stevec across 给出了一个警告,警告信息:在 `filter()` 中使用 `across()` 已被弃用,请使用 `if_any()` 或 `if_all()`。 - Rui Barradas
1
@stevec if_any()默认将is.infinite应用于所有列。where(is.numeric)使其仅适用于数字列,从而提高效率。 - Darren Tsai
显示剩余3条评论

1
根据文档,help("is.infinite"),细节部分的最后一段:

这三个函数都是通用的:您可以编写处理特定对象类别的方法,请参见InternalMethods

因此,一个解决方案是为is.finiteis.infiniteis.nan编写.list.data.frame方法。但要注意,如果您使用的系统不支持这些方法,那么您将会得到本问题中的错误提示。
is.finite.list <- function(x) {
  x[] <- lapply(x, base::is.finite)
  x
}
is.finite.data.frame <- function(x) {
  x[] <- lapply(x, base::is.finite)
  x
}
is.infinite.list <- function(x) {
  x[] <- lapply(x, base::is.infinite)
  x
}
is.infinite.data.frame <- function(x) {
  x[] <- lapply(x, base::is.infinite)
  x
}
is.nan.list <- function(x) {
  x[] <- lapply(x, base::is.nan)
  x
}
is.nan.data.frame <- function(x) {
  x[] <- lapply(x, base::is.nan)
  x
}

my_data <- data.frame(column1 = c(Inf, 5, 3,4,5), 
                      column2 = c(1, Inf, -Inf, NA, 33))

is.infinite(my_data)
#>   column1 column2
#> 1    TRUE   FALSE
#> 2   FALSE    TRUE
#> 3   FALSE    TRUE
#> 4   FALSE   FALSE
#> 5   FALSE   FALSE

is.finite(my_data)
#>   column1 column2
#> 1   FALSE    TRUE
#> 2    TRUE   FALSE
#> 3    TRUE   FALSE
#> 4    TRUE   FALSE
#> 5    TRUE    TRUE

is.nan(my_data)
#>   column1 column2
#> 1   FALSE   FALSE
#> 2   FALSE   FALSE
#> 3   FALSE   FALSE
#> 4   FALSE   FALSE
#> 5   FALSE   FALSE

# The question code line throwing the error
my_data[rowSums(is.infinite(my_data)) > 0, ]
#>   column1 column2
#> 1     Inf       1
#> 2       5     Inf
#> 3       3    -Inf

创建于2022年8月5日,使用reprex包(v2.0.1)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接