【问题标题】:R: Split weighted column into equal-sized bucketsR:将加权列拆分为大小相等的桶
【发布时间】:2016-02-08 18:12:39
【问题描述】:

我想使用 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 &lt;- cut_number(df$x,3)x 分割成 3 个具有大致相同数量观察值的桶。但是我如何考虑到每一行都用一些观察值加权的事实呢?我想避免将每一行拆分为 weight 行,因为原始数据框已经有数百万行。

【问题讨论】:

  • 您能否详细说明您希望如何制作这些水桶?存储桶 1 是否应该包含 x1-xn、存储桶 2 xn+1-xm 等?或者每个桶是否应该包含接近 sum(weight)/number_of_buckets x's?
  • 后者:每个桶应该包含尽可能接近 sum(weight)/number_of_buckets x 的值。
  • 这似乎是一个创建间隔的简单问题,但我不清楚所需的输出。如果你的数据是df &lt;- data.frame(x=1:6, weight=c(1,1,1,1,4,1)),你是把桶画成123|455|556还是123|45|6|表示桶边界)?
  • 在我的应用程序中,每一行都应该分配一个唯一的桶。所以在你建议的两个分区中,前者是不可接受的,我会选择后者。
  • 我的回答对你有用吗?

标签: r dplyr


【解决方案1】:

根据 cmets,我认为这可能是您正在寻找的区间集。为它的一般 un-R-ness 道歉:

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

【讨论】:

    【解决方案2】:

    这是另一种方法,基于我的假设,即您总共有 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-07
      • 1970-01-01
      • 2017-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      相关资源
      最近更新 更多