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

时间:2009-01-14 23:09:03

标签: r vector

所以早些时候,我回答了自己关于在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循环。有什么想法吗?

3 个答案:

答案 0 :(得分:8)

这是另一种非常R型的生成总和的方法。生成一个与输入向量一样长的向量,只包含n个元素的重复总和。然后,从sums向量中减去原始向量。结果:一个向量(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

答案 1 :(得分:8)

奇怪的是,学习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);

答案 2 :(得分:0)

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

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

tapply生成一个统计表(在这种情况下为sum;第三个参数),该表由作为第二个参数给出的参数分组。例如

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年将仅返回列。)