将数字向量拆分为不相等的部分,然后将自定义函数应用于每个部分

时间:2014-06-09 18:13:48

标签: r for-loop vector split

我有一个长序列的1和0表示鸟类孵化模式,1表示鸟巢,0表示关闭。

    > Fake.data<- c(1,1,1,1,1,0,0,1,1,1,1,0,0,0,1,1,1,1,0,1,1,1,1,0,0,1,1,1,1,1,0,0,0,0,1,1,0,1,0)

作为终点,我基本上喜欢每个ON周期和连续OFF周期之间的比率的单个值。理想情况下,这应该是Fake.data这样的矢量

    [1] 0.4  0.75  0.25  0.5  0.8  0.5  1 (I just typed this out!) 

到目前为止,我已使用split()

将矢量拆分为多个部分
    > Diff<-diff(Fake.data)
    > SPLIT<-split(Fake.data, cumsum(c(1, Diff > 0 )))
    > SPLIT

返回......

    $`1`
    [1] 1 1 1 1 1 0 0
    $`2`
    [1] 1 1 1 1 0 0 0
    $`3`
    [1] 1 1 1 1 0
    $`4`
    [1] 1 1 1 1 0 0
    $`5`
    [1] 1 1 1 1 1 0 0 0 0
    $`6`
    [1] 1 1 0
    $`7`
    [1] 1 0

所以我可以使用

获得单个拆分组的比率
    > SPLIT$'1'<- ((length(SPLIT$'1'))-(sum(SPLIT$'1')))/sum(SPLIT$'1')
    > SPLIT$'1'
    [1] 0.4

然而,在我的数据中,我有几千个这样做,并希望应用某种tapply()或for()循环来自动计算所有这些并将其放入单个向量中。我已经尝试了这些方法中的每一个都没有成功,因为split()输出结构似乎不适合这些函数?

我创建一个新的向量来接收for()循环输出

    ratio<-rep(as.character(NA),(length(SPLIT)))

然后使用上面的代码尝试for()循环,该代码适用于单次运行。

    for(i in SPLIT$'1':'7')
    {ratio[i]<-((length(SPLIT$'[i]'))-(sum(SPLIT$'[i]')))/sum(SPLIT$'[i]')}

我得到的是......

[1]&#34; NaN&#34; &#34; NaN的&#34; &#34; NaN的&#34; &#34; NaN的&#34; &#34; NaN的&#34; &#34; NaN的&#34; NA

尝试了很多其他的变化,但现在真的卡住了!

2 个答案:

答案 0 :(得分:3)

我认为你与你的态势非常接近。 sapply函数非常乐意使用列表。我只想改变最后一步

sapply(SPLIT, function(x) sum(x==0)/sum(x==1))

返回

   1    2    3    4    5    6    7 
0.40 0.75 0.25 0.50 0.80 0.50 1.00 

包含您的示例数据。无需额外的包裹。

答案 1 :(得分:1)

以下是两种可能性:

1)使用rle计算长度,然后在if语句中,如果数据以0开头,则不包括第一个长度,以便我们放心我们从1开始。最后使用动物园包中的rollapply来计算比率:

library(zoo)

lengths <- rle(Fake.data)$lengths
if (Fake.data[1] == 0) lengths <- lengths[-1]

rollapply(lengths, 2, by = 2, function(x) x[2]/x[1])

,并提供:

[1] 0.40 0.75 0.25 0.50 0.80 0.50 1.00

如果我们知道数据始终以1开头,则可以删除if行。

2)如果我们可以假设系列始终以1开头并以0结尾,那么这一个班轮将起作用:

with( rle(Fake.data), lengths[values == 0] / lengths[values == 1] )

给出与上述相同的答案。