我正在使用与此类似的数据:
cat value n
1 100 18
2 0 19
3 -100 15
4 100 13
5 0 17
6 -100 18
在实际数据中,有许多cat
和value
可以是-100到100之间的任何数字(无NA
)。
我想要做的是根据value
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
语句。我希望你能比我更容易地解决这个问题。提前致谢!
答案 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 :value
与indx
总结[,.(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