gpt4 book ai didi

r - 按相等的桶聚合数据框

转载 作者:行者123 更新时间:2023-12-04 10:45:37 27 4
gpt4 key购买 nike

我想通过等量的 data.frame 中变量之一的累积总和来聚合 R data.frame。我在谷歌上搜索了很多,但可能我不知道找到任何有用的正确术语。

假设我有这个 data.frame:


> x <- data.frame(cbind(p=rnorm(100, 10, 0.1), v=round(runif(100, 1, 10))))
> head(x)
p v
1 10.002904 4
2 10.132200 2
3 10.026105 6
4 10.001146 2
5 9.990267 2
6 10.115907 6
7 10.199895 9
8 9.949996 8
9 10.165848 8
10 9.953283 6
11 10.072947 10
12 10.020379 2
13 10.084002 3
14 9.949108 8
15 10.065247 6
16 9.801699 3
17 10.014612 8
18 9.954638 5
19 9.958256 9
20 10.031041 7

我想将 x 减少到一个较小的 data.frame,其中每行包含 p 的加权平均值,由 v 加权,对应于 v 的 n 个单位的数量。这样的东西:

> n <- 100
> cum.v <- cumsum(x$v)
> f <- cum.v %/% n
> x.agg <- aggregate(cbind(v*p, v) ~ f, data=x, FUN=sum)
> x.agg$'v * p' <- x.agg$'v * p' / x.agg$v
> x.agg
f v * p v
1 0 10.039369 98
2 1 9.952049 94
3 2 10.015058 104
4 3 9.938271 103
5 4 9.967244 100
6 5 9.995071 69

第一个问题,我想知道上面的代码是否有更好(更有效的方法)。第二个更重要的问题是 如何更正上面的代码以获得更精确的分桶 .即, x.agg中的每一行应该完全包含 100 v的单位,而不仅仅是上面的情况。例如,第一行包含 x 的前 17 行的聚合。对应于 v 的 98 个单位.下一行(第 18 行)包含 5 个单位的 v并完全包含在下一个存储桶中。我想要实现的是将第 18 行的 2 个单位归于第一个存储桶,其余 3 个单位归于下一个存储桶。

在此先感谢您提供的任何帮助。

最佳答案

这是另一种方法,无需重复每个 p v次。我理解的方式是,它越过 100 的地方(见下文)

18  9.954638  5  98
19 9.958256 9 107

应改为:
18    9.954638  5  98
19.1 9.958256 2 100 # ---> 2 units will be considered with previous group
19.2 9.958256 7 107 # ----> remaining 7 units will be split for next group

代码:
n <- 100
# get cumulative sum, an id column (for retrace) and current group id
x <- transform(x, cv = cumsum(x$v), id = seq_len(nrow(x)), grp = cumsum(x$v) %/% n)

# Paste these two lines in R to install IRanges
source("http://bioconductor.org/biocLite.R")
biocLite("IRanges")

require(IRanges)
ir1 <- successiveIRanges(x$v)
ir2 <- IRanges(seq(n, max(x$cv), by=n), width=1)
o <- findOverlaps(ir1, ir2)

# gets position where multiple of n(=100) occurs
# (where we'll have to do something about it)
pos <- queryHits(o)
# how much do the values differ from multiple of 100?
val <- start(ir2)[subjectHits(o)] - start(ir1)[queryHits(o)] + 1
# we need "pos" new rows of "pos" indices
x1 <- x[pos, ]
x1$v <- val # corresponding values
# reduce the group by 1, so that multiples of 100 will
# belong to the previous row
x1$grp <- x1$grp - 1
# subtract val in the original data x
x$v[pos] <- x$v[pos] - val
# bind and order them
x <- rbind(x1,x)
x <- x[with(x, order(id)), ]
# remove unnecessary entries
x <- x[!(duplicated(x$id) & x$v == 0), ]
x$cv <- cumsum(x$v) # updated cumsum

x$id <- NULL
require(data.table)
x.dt <- data.table(x, key="grp")
x.dt[, list(res = sum(p*v)/sum(v), cv = tail(cv, 1)), by=grp]

在您的数据上运行:
#    grp       res  cv
# 1: 0 10.037747 100
# 2: 1 9.994648 114

在@geektrader 的数据上运行:
#    grp       res  cv
# 1: 0 9.999680 100
# 2: 1 10.040139 200
# 3: 2 9.976425 300
# 4: 3 10.026622 400
# 5: 4 10.068623 500
# 6: 5 9.982733 562

这是一个相对大数据的基准:
set.seed(12345)
x <- data.frame(cbind(p=rnorm(1e5, 10, 0.1), v=round(runif(1e5, 1, 10))))

require(rbenchmark)
benchmark(out <- FN1(x), replications=10)

# test replications elapsed relative user.self
# 1 out <- FN1(x) 10 13.817 1 12.586

大约需要 1.4 秒 在 1e5 行上。

关于r - 按相等的桶聚合数据框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15095097/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com