我想使用类似dplyr' cut_number
的内容将列拆分为具有大致相同数量的观察值的存储桶,其中我的数据集采用紧凑形式,其中每行都有一个权重(数字)观察)。
示例数据框:
df <- data.frame(
x=c(18,17,18.5,20,20.5,24,24.4,18.3,31,34,39,20,19,34,23),
weight=c(1,10,3,6,19,20,34,66,2,3,1,6,9,15,21)
)
如果每行有一次x观察,我只需使用df$bucket <- cut_number(df$x,3)
将x
分段为3个桶,观察次数大致相同。但是,我如何考虑每一行用一些观察值加权的事实?我希望避免将每一行拆分为weight
行,因为原始数据帧已经有数百万行。
答案 0 :(得分:1)
这是另一种方法,基于我的假设你总共有x1 * weight1 + x2 * weight2 + .....观察。此外,每个“独特”观察只能在一个桶中。该方法使用排序和权重的累积总和来创建桶。
#sort data
df <- df[order(df$x),]
#calculate cumulative weights (this is why we sort)
df$cumulative_weight <- cumsum(df$weight)
#create bucket by cumulative weight
n_buckets <- 3
df$bucket <- cut(df$cumulative_weight, n_buckets)
#check: calculate total number of observations per bucket
> aggregate(weight~bucket,FUN=sum, data=df)
bucket weight
1 (9.79,78.7] 77
2 (78.7,147] 64
3 (147,216] 75
答案 1 :(得分:1)
根据评论,我认为这可能是您正在寻找的区间集。对它的一般解释道歉:
dfTest <- data.frame(x=1:6, weight=c(1,1,1,1,4,1))
f <- function(df, n) {
interval <- round(sum(df$weight) / n)
buckets <- vector(mode="integer", length(nrow(df)))
bucketNum <- 1
count <- 0
for (i in 1:nrow(df)) {
count <- count + df$weight[i]
buckets[i] <- bucketNum
if (count >= interval) {
bucketNum <- bucketNum + 1
count <- 0
}
}
return(buckets)
}
运行此函数会按以下方式执行以下项目:
dfTest$bucket <- f(dfTest, 3)
# x weight bucket
# 1 1 1 1
# 2 2 1 1
# 3 3 1 1
# 4 4 1 2
# 5 5 4 2
# 6 6 1 3
对于你的例子:
df$bucket <- f(df, 3)
# x weight bucket
# 1 18.0 1 1
# 2 17.0 10 1
# 3 18.5 3 1
# 4 20.0 6 1
# 5 20.5 19 1
# 6 24.0 20 1
# 7 24.4 34 1
# 8 18.3 66 2
# 9 31.0 2 2
# 10 34.0 3 2
# 11 39.0 1 2
# 12 20.0 6 3
# 13 19.0 9 3
# 14 34.0 15 3
# 15 23.0 21 3