这四种查找与谓词匹配的向量的第一个元素的方法如何比较?
How do these four methods for finding the first element of a vector that matches a predicate compare?
我发现了很多这样的方法。首先,我将设置我的数据和谓词函数:
set.seed(123)
data<-sample(66,20)
print(data)
#31 51 14 3 42 50 54 43 37 52 64 60 25 26 27 5 57 28 9 29
isFour<-function(x) x==4 #Not in our data
isFourteen<-function(x) x==14 #Element 3 of our data
我知道有四种方法可以找到与我们的谓词函数匹配的 data
的第一个元素所在的索引。以下情况都有 data
,其中与 isFourteen
的唯一匹配出现。他们都是return3
.
which(isFourteen(data))[1]
which.max(isFourteen(data))
match(TRUE,isFourteen(data))
Position(isFourteen,data)
当有不唯一的匹配时,它们都是return第一个匹配的索引。在这些方法中,在这种情况下唯一可以改变其行为的方法是 which
(因为我们可以使用 [
到 select 除了 1
以外的元素)和 Position
(传递 right=TRUE
它将找到最后一个匹配索引而不是第一个)。
最有趣的情况是没有匹配项:
which(isFour(data))[1]
#Returns NA because we're subsetting integer(0). No argument can customize this output.
which.max(isFour(data))
#Returns 1 because the only value is FALSE. This is a dangerous answer.
match(TRUE,isFour(data))
#Returns NA, but can be customised by the nomatch argument e.g. nomatch = stop("IDIOT!")
#match() also has the incomparables argument, but I've never found a use for it.
Position(isFour,data)
#Same as match, but doesn't have an incomparables argument.
是否有任何 objective 原因 - 例如绩效、文化或安全 - 这些方法中哪一种是首选?
对于以上三个类别,我注意到以下几点:
- 性能:
Position
完全用 R 编写,讨论中的所有其他函数主要用 C 编写。
- 文化:
which.max
的文档建议使用 match(TRUE,...)
方法,which
的文档建议 match
是有效的(这并不奇怪,which
找到每个元素和子集, match
只找到第一个)。 match
的这些建议,再加上我从未在它自己的文档之外看到 Position
的事实,表明 match
更符合惯用语。
- 安全:我已经证明
which.max
存在重大危险。至于其他人,which
无法保护自己免受 NA
的伤害,但 Position
和 match
可以。
为了避免基于意见的答案,我强烈建议任何答案都包括某种基准测试和证明他们声称使用有风险的任何功能缺乏安全性。
尽管有您的要求,但我想很多都是基于意见;尽管如此,这是我的看法。
这真的取决于用例。甚至您的问题也可能隐藏歧义;在这里我看到两个不同的任务:
- 找到
list
的第一个符合条件 的元素(的位置)
- 在
logical
向量中找到第一个 TRUE 值(的位置)。
当然,第二个任务也解决了第一个任务,但是需要为列表的每个元素应用谓词。
很多与 R 中的矢量化有关:对于许多任务,即使“算法上”错误,评估列表中每个元素的谓词然后找到 TRUE
位置也会更方便。这当然是你的例子的情况:毫无疑问,鉴于 isFour
和另一个的定义方式 match
更喜欢:我们不介意检查 [=15 的每个元素=] 因为操作非常快,即使在结束之前可以停下来得到答案。这是因为,如果我们“去向量化”你的函数,平均而言我们会减慢很多事情,因为子集和检查单个元素要慢得多。考虑到我在这里使用的列表不是 R 含义(list
对象),而是作为值的集合。
另一方面,Position
被认为在您的数据为 list
and/or 时使用 f
函数未矢量化且非常昂贵。想象一下,例如 f
包括训练机器学习模型,根据一些数据对其进行评估并获取一些性能统计数据。我们有一个我们想要训练的算法列表,我们想要在达到不错的性能时停止。在这种情况下,我们不想训练列表中的每个可能模型(超级昂贵),而是尽快停止。因此,我们将使用 Position
(另请参阅其源代码以了解原因)。
关于我在开头概述的两个任务,您的所有解决方案都处理第二个任务,而只有 Position
只解决第一个任务。
所以,一般来说:
- 如果谓词是向量化的且高效,则选择
match
;
- 如果谓词非常昂贵,请使用
Position
。
在任何情况下都没有理由使用其他两个解决方案:which
和 which.max
主要用于其他任务而不是确定 TRUE 值的位置(当然,即使他们可以)。
为了更好地概述 match
解决方案与 Position
解决方案之间的区别,这里是一个回顾。
- 对于
match
,isFour
函数应用于输入的 每个元素,并且仅在 [之后] match
实际行动。当然,对于示例的特定任务,更好的方法是 match(4, data)
,因为一旦找到 4,match
就会在内部停止。但重要的一点是 isFour
应用于您实施中的整个输入。
- 对于
Position
,您传递的是函数,而不是其应用程序的结果。然后,该函数逐个元素地应用,当满足条件时退出,而不必处理整个输入。
现在应该清楚什么是首选:它取决于“去向量化”函数的成本与不处理整个输入的收益。
我发现了很多这样的方法。首先,我将设置我的数据和谓词函数:
set.seed(123)
data<-sample(66,20)
print(data)
#31 51 14 3 42 50 54 43 37 52 64 60 25 26 27 5 57 28 9 29
isFour<-function(x) x==4 #Not in our data
isFourteen<-function(x) x==14 #Element 3 of our data
我知道有四种方法可以找到与我们的谓词函数匹配的 data
的第一个元素所在的索引。以下情况都有 data
,其中与 isFourteen
的唯一匹配出现。他们都是return3
.
which(isFourteen(data))[1]
which.max(isFourteen(data))
match(TRUE,isFourteen(data))
Position(isFourteen,data)
当有不唯一的匹配时,它们都是return第一个匹配的索引。在这些方法中,在这种情况下唯一可以改变其行为的方法是 which
(因为我们可以使用 [
到 select 除了 1
以外的元素)和 Position
(传递 right=TRUE
它将找到最后一个匹配索引而不是第一个)。
最有趣的情况是没有匹配项:
which(isFour(data))[1]
#Returns NA because we're subsetting integer(0). No argument can customize this output.
which.max(isFour(data))
#Returns 1 because the only value is FALSE. This is a dangerous answer.
match(TRUE,isFour(data))
#Returns NA, but can be customised by the nomatch argument e.g. nomatch = stop("IDIOT!")
#match() also has the incomparables argument, but I've never found a use for it.
Position(isFour,data)
#Same as match, but doesn't have an incomparables argument.
是否有任何 objective 原因 - 例如绩效、文化或安全 - 这些方法中哪一种是首选?
对于以上三个类别,我注意到以下几点:
- 性能:
Position
完全用 R 编写,讨论中的所有其他函数主要用 C 编写。 - 文化:
which.max
的文档建议使用match(TRUE,...)
方法,which
的文档建议match
是有效的(这并不奇怪,which
找到每个元素和子集,match
只找到第一个)。match
的这些建议,再加上我从未在它自己的文档之外看到Position
的事实,表明match
更符合惯用语。 - 安全:我已经证明
which.max
存在重大危险。至于其他人,which
无法保护自己免受NA
的伤害,但Position
和match
可以。
为了避免基于意见的答案,我强烈建议任何答案都包括某种基准测试和证明他们声称使用有风险的任何功能缺乏安全性。
尽管有您的要求,但我想很多都是基于意见;尽管如此,这是我的看法。
这真的取决于用例。甚至您的问题也可能隐藏歧义;在这里我看到两个不同的任务:
- 找到
list
的第一个符合条件 的元素(的位置)
- 在
logical
向量中找到第一个 TRUE 值(的位置)。
当然,第二个任务也解决了第一个任务,但是需要为列表的每个元素应用谓词。
很多与 R 中的矢量化有关:对于许多任务,即使“算法上”错误,评估列表中每个元素的谓词然后找到 TRUE
位置也会更方便。这当然是你的例子的情况:毫无疑问,鉴于 isFour
和另一个的定义方式 match
更喜欢:我们不介意检查 [=15 的每个元素=] 因为操作非常快,即使在结束之前可以停下来得到答案。这是因为,如果我们“去向量化”你的函数,平均而言我们会减慢很多事情,因为子集和检查单个元素要慢得多。考虑到我在这里使用的列表不是 R 含义(list
对象),而是作为值的集合。
另一方面,Position
被认为在您的数据为 list
and/or 时使用 f
函数未矢量化且非常昂贵。想象一下,例如 f
包括训练机器学习模型,根据一些数据对其进行评估并获取一些性能统计数据。我们有一个我们想要训练的算法列表,我们想要在达到不错的性能时停止。在这种情况下,我们不想训练列表中的每个可能模型(超级昂贵),而是尽快停止。因此,我们将使用 Position
(另请参阅其源代码以了解原因)。
关于我在开头概述的两个任务,您的所有解决方案都处理第二个任务,而只有 Position
只解决第一个任务。
所以,一般来说:
- 如果谓词是向量化的且高效,则选择
match
; - 如果谓词非常昂贵,请使用
Position
。
在任何情况下都没有理由使用其他两个解决方案:which
和 which.max
主要用于其他任务而不是确定 TRUE 值的位置(当然,即使他们可以)。
为了更好地概述 match
解决方案与 Position
解决方案之间的区别,这里是一个回顾。
- 对于
match
,isFour
函数应用于输入的 每个元素,并且仅在 [之后]match
实际行动。当然,对于示例的特定任务,更好的方法是match(4, data)
,因为一旦找到 4,match
就会在内部停止。但重要的一点是isFour
应用于您实施中的整个输入。 - 对于
Position
,您传递的是函数,而不是其应用程序的结果。然后,该函数逐个元素地应用,当满足条件时退出,而不必处理整个输入。
现在应该清楚什么是首选:它取决于“去向量化”函数的成本与不处理整个输入的收益。