R:将加权列拆分为等大小的桶

时间:2016-02-08 18:12:40

标签: r dplyr

我想使用类似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行,因为原始数据帧已经有数百万行。

2 个答案:

答案 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