向量化我的想法:R 中的向量运算

Posted

技术标签:

【中文标题】向量化我的想法:R 中的向量运算【英文标题】:Vectorize my thinking: Vector Operations in R 【发布时间】:2010-10-01 11:56:49 【问题描述】:

所以早些时候我回答了我自己关于在 R 中思考向量的问题。但现在我遇到了另一个我无法“向量化”的问题。我知道向量更快,循环更慢,但我不知道如何在向量方法中做到这一点:

我有一个数据框(出于情感原因,我喜欢将其称为 my.data),我想对其进行全面的边际分析。我需要一次删除某些元素并“赋值”数据框,然后我需要通过仅删除下一个元素来再次进行迭代。然后再做一次……再一次……这个想法是对我的数据子集进行全面的边际分析。无论如何,我无法想象如何以矢量有效的方式做到这一点。

我已经缩短了代码的循环部分,它看起来像这样:

for (j in my.data$item[my.data$fixed==0])  # <-- selects the items I want to loop 
                                            #     through
    my.data.it <- my.data[my.data$item!= j,] # <-- this kicks item j out of the list
    sum.data <-aggregate(my.data.it, by=list(year), FUN=sum, na.rm=TRUE) #<-- do an
                                                                         # aggregation

    do(a.little.dance) && make(a.little.love) -> get.down(tonight) # <-- a little
                                                                   #  song and dance

    delta <- (get.love)                                         # <-- get some love
    delta.list<-append(delta.list, delta, after=length(delta.list)) #<-- put my love
                                                                    #    in a vector 

所以很明显我在中间砍掉了一堆东西,只是为了让它不那么笨拙。目标是使用更有效的向量来删除 j 循环。有什么想法吗?

【问题讨论】:

@joran:编辑 30 个月前的问题必须有奖励。 :) 死灵法师的某个版本,也许吧? 好主意。我在想像自然历史博物馆馆长那样的事情可能不那么病态。或者侏罗纪公园? 我很震惊这个问题持续了三年,没有人评论关于速度的部分。矢量化通常会产生速度提升,但并非总是如此;可读性往往是更重要的原因。 @gsk3,请记住,当我最初提出这个问题时,只有大约 5 个人在阅读 [r] 问题 :) 【参考方案1】:

这似乎是另一种非常 R 类型的生成总和的方法。生成一个与输入向量一样长的向量,只包含 n 个元素的重复总和。然后,从 sum 向量中减去原始向量。结果:一个向量(isums),其中每个条目都是您的原始向量减去第 i 个元素。

> (my.data$item[my.data$fixed==0])
[1] 1 1 3 5 7
> sums <- rep(sum(my.data$item[my.data$fixed==0]),length(my.data$item[my.data$fixed==0]))
> sums
[1] 17 17 17 17 17
> isums <- sums - (my.data$item[my.data$fixed==0])
> isums
[1] 16 16 14 12 10

【讨论】:

这很好地提醒了我们如何以 r-esque 方式思考。在我的应用程序中,总和之后的步骤似乎给我应用你提到的方法带来了一些问题。但我投票赞成,以便给你一些声望点。我很高兴在这里看到另一个 R 人!【参考方案2】:

奇怪的是,学习 R 中的向量化帮助我习惯了基本的函数式编程。一种基本技术是将循环内的操作定义为函数:

data = ...;
items = ...;

leave_one_out = function(i) 
   data1 = data[items != i];
   delta = ...;  # some operation on data1
   return delta;



for (j in items) 
   delta.list = cbind(delta.list, leave_one_out(j));

要进行矢量化,您只需将 for 循环替换为 sapply 映射函数即可:

delta.list = sapply(items, leave_one_out);

【讨论】:

【参考方案3】:

这不是答案,但我想知道这个方向是否有任何见解:

> tapply((my.data$item[my.data$fixed==0])[-1], my.data$year[my.data$fixed==0][-1], sum)

tapply 生成按作为第二个参数给出的参数分组的统计信息表(在本例中为总和;第三个参数)。例如

2001 2003 2005 2007
1    3    5    7

[-1] 表示法从选定行中删除观察(行)之一。因此,您可以循环并在每个循环上使用 [-i]

for (i in 1:length(my.data$item)) 
  tapply((my.data$item[my.data$fixed==0])[-i], my.data$year[my.data$fixed==0][-i], sum)

请记住,如果您有任何年份只有 1 次观察,那么连续的 tapply 调用返回的表将不会具有相同数量的列。 (即,如果您删除了 2001 年的唯一观察值,那么 2003、2005 和 2007 年将仅返回 te 列)。

【讨论】:

以上是关于向量化我的想法:R 中的向量运算的主要内容,如果未能解决你的问题,请参考以下文章

R语言向量化运算:apply函数族用法心得

R语言——水仙花数(向量化运算)

R语言——水仙花数(向量化运算)

向量化

如何使用向量化代码从 MATLAB 中的两个向量生成所有对?

R中真正快速的词ngram向量化