索引到向量时的自引用

Posted

技术标签:

【中文标题】索引到向量时的自引用【英文标题】:Self reference when indexing into a vector 【发布时间】:2014-10-19 22:01:15 【问题描述】:

在 R 中,有没有办法从向量中引用向量?

假设我有长名称的向量:

my.vector.with.a.long.name <- 1:10

而不是这样:

my.vector.with.a.long.name[my.vector.with.a.long.name > 5]

这样的东西会很好:

> my.vector.with.a.long.name[~ > 5]
[1]  6  7  8  9 10

或者通过函数索引会很方便:

> my.vector.with.a.long.name[is.even]
[1]  2  4  6  8 10

是否有已经支持这个的包?

【问题讨论】:

不知道为什么不能创建自己的函数来执行建议的操作,例如myFunc &lt;- function(x, y) x[x &gt; y] ; is.even &lt;- function(x) x[(x %% 2) == 0] ; myFunc(my.vector.with.a.long.name, 5) ; is.even(my.vector.with.a.long.name) 或使用制表符自动完成您的(不必要的)长名称? 没试过,但可能是require(magrittr); my.stupid.name %&gt;% [&gt;5] 或类似的? 一个related 的问题,如果你愿意,它可能会提供一些关于如何实现它的想法。 @CarlWitthoft 我认为它不适用于 magrittr,请参阅:renkun.me/blog/2014/08/08/… 【参考方案1】:

因此,您基本上是在询问是否可以使用变量名称以外的其他名称来引用它。最简洁的答案是不。这就是变量名背后的全部想法。如果您想要一个更短的名称,请将其命名为更短的名称。

更长的答案取决于它。您实际上只是在使用长格式的逻辑索引。要使其更短/多次引用它而不必输入那个巨大的名称,只需将其保存在一个向量中,如下所示:

gt5 <- my.vector.with.a.long.name > 5
[1] FALSE FALSE FALSE FALSE FALSE TRUE...

my.vector.with.a.long.name[gt5]
[1] 6 7 8 9 10

只要函数返回索引或逻辑向量,您就可以对函数执行相同的操作。

dplyr 包允许您执行一些很酷的链接操作,您可以使用 %.% 运算符获取运算符的 LHS 并输入到 RHS 函数调用的第一个参数中。

在 dplyr 包中使用这样的话很酷:

data %.% group_by(group.var) %.% summarize(Mean=mean(ID))

代替:

summarize(group_by(data, group.var), Mean=mean(ID)).

【讨论】:

你可以,但这非常浪费内存,因为 AFAIK 在完全没有必要这样做时会创建一个全新的对象 gt5 是的,gt5 创建了一个新的逻辑向量,但显然这是一个微不足道的例子。如果您要重复使用索引或者创建起来很复杂,我喜欢创建这些索引对象。 @Carl Witthoft:进行分析,您会发现使用上面给出的代码时会发生完全相同的情况。这与 OP 的代码完全相同,除了明确说明。所以内存占用是一样的。 @JorisMeys 但向量 my.vector.with.a.long.name &gt; 5 会在下一次垃圾回收时被删除,而 gt5 不会。 @SeñorO 这就是为什么我总是在课堂上强调临时对象比其他任何东西都更具有可读性,并且应该尽可能删除。不仅是为了内存问题,也是为了避免通用计数器的错误,例如称为i。除此之外,保留它可能是有益的,以避免不得不多次重新计算同一事物(正如您在代码中经常看到的那样,尤其是 OP 所指的构造)。【参考方案2】:

您可以轻松地创建另一个名称更短的对象:

my.vector.with.a.long.name <- 1:10

mm = my.vector.with.a.long.name 

mm
 [1]  1  2  3  4  5  6  7  8  9 10

mm[mm<5]
[1] 1 2 3 4

mm[mm>5]
[1]  6  7  8  9 10

为什么要使用其他包和复杂的代码?

【讨论】:

【参考方案3】:

您可以使用允许通过. 进行自引用的管道:

library(pipeR)
my.vector.with.a.long.name %>>% `[`(.>5)
[1]  6  7  8  9 10
my.vector.with.a.long.name %>>% `[`(.%%2==0)
[1]  2  4  6  8 10

【讨论】:

是的。我的解决方案是foo %&gt;&gt;% (.[(.&gt;5)]),我相信它和你的一样......但是你在这里赢得了 CodeGolf :-)【参考方案4】:

Filter 函数可以帮助解决这个问题

my.vector.with.a.long.name <- 1:10
Filter(function(x) x%%2==0, my.vector.with.a.long.name)

is.even <- function(x) x%%2==0
Filter(is.even, my.vector.with.a.long.name)

【讨论】:

以上是关于索引到向量时的自引用的主要内容,如果未能解决你的问题,请参考以下文章

如何通过C ++中的数据获得向量的索引

总结并列出 dplyr 中的自定义索引

使用不同方式对具有数字索引的data.table列进行子集化时的结果不同

优雅的索引到向量/矩阵的末尾

矩阵运算:索引逻辑到数值比较的不对称向量

索引 CHOLMOD 密集向量数组