计算data.frame

时间:2015-07-25 16:57:52

标签: r

我正在使用与此类似的数据:

cat    value  n
  1      100 18
  2        0 19
  3     -100 15
  4      100 13
  5        0 17
  6     -100 18

在实际数据中,有许多catvalue可以是-100到100之间的任何数字(无NA)。

我想要做的是根据value

定义的terciles计算n的平均值

因此,举例来说,因为sum(n)=100我要做的就是让n尽可能接近33并计算value的平均值。所以对于第一个tercile,18不是33,所以我需要从cat = 2中取15个值。所以第一个tercile的平均值应该是(100*18+0*15)/(18+15)。第二个tercile将是来自n = 2的剩余cat s,然后到达33:(0*4+-100*15+100*13+0*1)/(4+15+13+1)所需的数量。类似于最后一个tercile。

我开始写这篇文章,但结果却出现了许多令人讨厌的for循环和if语句。我希望你能比我更容易地解决这个问题。提前致谢!

4 个答案:

答案 0 :(得分:2)

data.table的解决方案:

setDT(df)[rep(1:.N,n)
          ][,indx:=c(rep("a",33),rep("b",33),rep("c",34))
            ][,.(mean_val_indx=mean(value)),by=indx]

这给出了:

   indx mean_val_indx
1:    a     54.545455
2:    b     -6.060606
3:    c    -52.941176

对于数据的三个部分,value的含义是什么。

在中间步骤中分解:

1 :根据n

重新排列行
setDT(df)[rep(1:.N,n)]

这给了(缩短):

     cat value  n
  1:   1   100 18
  2:   1   100 18
....
 17:   1   100 18
 18:   1   100 18
 19:   2     0 19
 20:   2     0 19
....
 36:   2     0 19
 37:   2     0 19
 38:   3  -100 15
....
 99:   6  -100 18
100:   6  -100 18

2 :使用[,indx:=c(rep("a",33),rep("b",33),rep("c",34))]

创建索引
setDT(df)[rep(1:.N,n)
          ][,indx:=c(rep("a",33),rep("b",33),rep("c",34))]

这给出了:

> dt
     cat value  n indx
  1:   1   100 18    a
  2:   1   100 18    a
....
 17:   1   100 18    a
 18:   1   100 18    a
 19:   2     0 19    a
 20:   2     0 19    a
....
 32:   2     0 19    a
 33:   2     0 19    a
 34:   2     0 19    b
 35:   2     0 19    b
....
 99:   6  -100 18    c
100:   6  -100 18    c

3 valueindx总结[,.(mean_val_indx=mean(value)),by=indx]

答案 1 :(得分:1)

您可以尝试这样的事情,data是您的示例数据框:

    longData<-unlist(apply(data[,c("value","n")],1,function(x){
      rep(x["value"],x["n"])      
    }))

    aggregate(longData,list(cut(seq_along(longData),breaks=3,right=FALSE)),mean)

longData将是一个长度为100的向量,使用你的例子,18次重复-100次,19次重复0次等。

cut中的aggregate会将longData划分为三组,并计算每组的平均值。

答案 2 :(得分:0)

如果数据已经很长时间重复,那么&#34; n&#34;也许不需要。 以下解决方案不会这样做。而且,总和的1/3 &#34; n&#34; -values没有四舍五入到最接近的整数。 &#34; I&#34;是行数的向量,其中terciles结束。既然有可能 几个terciles在同一行结束,那些行号被复制。 结果是向量&#34; k&#34;。 对于每个索引&#34; j&#34; &#34;数据$ value&#34; *&#34;数据$ n&#34;的累积总和直到&#34; k [j]&#34; 封面&#34; ms [k [j]]&#34; terciles,所以&#34; ms [j] -j&#34;必须减去terciles 将积累的总和计算到&#34; j&#34; tercile。

m <- 3

sn <- sum(data$n)
ms <- m * cumsum(data$n) / sn
d  <- diff(c(0,floor(ms)))
i  <- which(d>0)
k  <- rep(i,d[i])
vn <- data$value * data$n

sums  <- cumsum(vn)[k] - (ms[k]-(1:m))*data$value[k]*sn/m
means <- m*diff(c(0,sums))/sn

terciles的手段是:

> means
[1]  54  -6 -54

在这个例子中&#34;我&#34;等于&#34; k&#34;。但如果用十分位数代替terciles, 即&#34; m&#34;不是3而是10,它们是截然不同的:

> m
[1] 10
> i
[1] 1 2 3 4 5 6
> k
 [1] 1 2 2 3 3 4 5 5 6 6
> means
 [1]  100   80    0  -30 -100   60   50    0  -80 -100

我比较了4个答案的速度,使用了8行的小例子:

> ##### "longData"-Answer #####
> 
> system.time( for ( i in 1:1000 ) { A1 <- f1(data) } )
       User      System verstrichen 
       3.48        0.00        3.49 

> ##### "sapply"-Answer #####
> 
> system.time( for ( i in 1:1000 ) { A2 <- f2(data) } )
       User      System verstrichen 
       1.00        0.00        0.99 

> ##### "data.table"Answer #####
> 
> system.time( for ( i in 1:1000 ) { A3 <- f3(data) } )
       User      System verstrichen 
       4.73        0.00        4.79 

> ##### this Answer #####
> 
> system.time( for ( i in 1:1000 ) { A4 <- f4(data) } )
       User      System verstrichen 
       0.43        0.00        0.44 

&#34; sapply&#34; -Answer甚至是假的:

> A1
     Group.1          x
1 [0.901,34)  54.545455
2    [34,67)  -6.060606
3   [67,100) -52.941176
> A2
    (0,33]    (33,67]   (67,100] 
-100.00000    0.00000   93.93939 
> A3
   indx mean_val_indx
1:    a     54.545455
2:    b     -6.060606
3:    c    -52.941176
> A4
[1]  54  -6 -54
> 

答案 3 :(得分:-1)

这与NicE基本相同,虽然可能作为组装代表和切割操作的不同方式有用:

 sapply(split( sort(unlist( mapply(rep, res$value, res$n) )), 
               cut(seq(sum(res$n)), breaks=c(0,33,67,100) )), 
        mean)

    (0,33]    (33,67]   (67,100] 
-100.00000    0.00000   93.93939