R - 使用函数过滤向量

44

我有一个类似于这个函数的函数:

isGoodNumber <- function(X) 
{
if (X==5) return(TRUE) else return(FALSE)
}

I have a vector:
v<-c(1,2,3,4,5,5,5,5)

我想获取一个包含v的元素且满足isGoodNumber(v) == TRUE的新向量。

我应该如何做?

尝试过 v [ isGoodNumber(v) == TRUE ],但它不起作用 :-)

谢谢!!


你能重写这个函数吗?还是这个函数已经被定义好了,你不能改变它? - Dason
2
我猜你的真实应用比这个例子更复杂,但对于你的例子 v[v==5] 将会起到作用。 - Chase
嗨@Dason,是的,我能够重写这个函数 :-) - MadSeb
@Chase:是的,实际应用比例子更加复杂,但不管怎样还是谢谢你! - MadSeb
我只是问一下,因为ifelse是if的向量化版本。在这个例子中使用if才会导致问题。有一些方法可以解决无法轻松向量化的函数,但在某些情况下,最好的解决方案是最初以向量化方式编写函数。 - Dason
@Dason。仅供记录(我猜您现在已经知道了),R中的ifelse并不是if的向量化版本。if函数旨在执行代码。它将执行第二个或第三个参数中的任何内容。执行的代码可能相当复杂,并且分配会保留在调用环境中。ifelse函数仅返回从两组可能值之间选择的值向量。在替代方案中包括分配将不成功。认为它们相似会导致错误的结论。 - IRTFM
5个回答

63

有一个名为 "Filter" 的函数可以完全满足您的需求:

Filter( isGoodNumber, v)
#[1] 5 5 5 5

有一种选择是创建一个向量化的函数,可以通过使用Vectorize函数(已经介绍过)或使用ifelse来编写,还有一种类似于"Filter"的函数。

可以选择创建一个向量化函数,通过使用Vectorize函数(如前所述),或编写ifelse函数,或创建类似于“Filter”的函数。

 isGoodNumber3 <- function(X) 
   { X[ ifelse(X==5, TRUE,FALSE)]
   }

 isGoodNumber3(v)
#[1] 5 5 5 5

4
这是唯一一个不需要重复 v 的答案,如果 v 是计算表达式,这是一件好事 - krlmlr
使用管道更容易 v %>% .[sapply(.,isGoodNumber)]. 引用了 v 对象,sapply 将 isGoodNumber 应用于 v 中的每个元素。 - Thomas Luechtefeld
@ThomasLuechtefeld。我们对“易用”的定义可能不同。管道方法看起来比‘v[sapply(v, isGoodNumber)]’更复杂,它们都不如Filter方法优雅。 - IRTFM
你是正确的,我的错误。 - Thomas Luechtefeld

37

我认为这里是最简单的方法

> v<-c(1,2,3,4,5,5,5,5)
> v[v==5]
[1] 5 5 5 5

27
你需要对该函数进行向量化处理才能在向量上调用它:
isGoodNumber = Vectorize(isGoodNumber)
v[isGoodNumber(v)]

9
使用mapply()函数:
> v <- c(1,2,3,4,5,5,5,5)
> newV <- mapply(function(X) { if (X==5) return(TRUE) else return(FALSE) }, v)
> newV
[1] FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE
> v[newV == TRUE]
[1] 5 5 5 5

6
你应该尽可能养成编写向量化函数的习惯。例如,如果你正在编写一个函数f(x),请确保它在x是向量而不仅仅是单个数字时也能工作。不要依赖Vectorize来完成这一点,因为对于非常大的向量,它会变得很慢。
一个有用的技巧是用ifelse替换if ... then ... else。例如:
isGoodNumber <- function(X) 
{
  ifelse(X==5, TRUE, FALSE)
}
v<-c(1,2,3,4,5,5,5,5)
v [ isGoodNumber(v) == TRUE ]

在这种情况下,你当然可以优化流程:
isGoodNumber <- function(X) return(X==5)

甚至只是

或者

v[v==5]

但是ifelse技巧通常更有用。


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