JuliaDB的自定义GroupBy函数

JuliaDB的自定义GroupBy函数,julia,Julia,我正在使用JuliaDBloadtable函数读取一些股票交易数据,我想对所有相同的日期进行分组,并应用一个自定义函数 自定义函数用于获取同一日期的交易组,并返回单个交易,交易量为总和,交易价格为交易量加权平均值。我可以得到体积的总和,但我很难得到体积加权平均值 function vol_weighted_avg(x) return (x.price .* x.volume) / sum(x.volume) end 这是函数,但不适用于 groupby(交易量加权平均值:日期) 我花了很长时间

我正在使用JuliaDB
loadtable
函数读取一些股票交易数据,我想对所有相同的日期进行分组,并应用一个自定义函数

自定义函数用于获取同一日期的交易组,并返回单个交易,交易量为总和,交易价格为交易量加权平均值。我可以得到体积的总和,但我很难得到体积加权平均值

function vol_weighted_avg(x)
return (x.price .* x.volume) / sum(x.volume)
end
这是函数,但不适用于
groupby(交易量加权平均值:日期)


我花了很长时间玩groupby,但我没有弄明白它,也没有遇到说明如何执行上述操作的文档。

您的代码有几个问题。我的答案是Julia 0.6和Julia 0.8.4。 您必须了解的是,
groupby
返回一个
NamedTuple
s的向量。因此,实现功能的最简单方法是:

vol_weighted_avg(x) =
    sum(getindex.(x, :price) .* getindex.(x,:volume)) / sum(getindex.(x,:volume))
您可以使用
StatsBase
中的
mean
实现相同的功能:

using StatsBase
vol_weighted_avg2(x) = mean(getindex.(x, :price), Weights(getindex.(x,:volume)))
不幸的是,如果您的数据非常大,这两个版本都不能很好地扩展。您可以为
OnlineStats
编写自定义加权平均值计算,但在这种情况下,我确实觉得有点麻烦。但是,在这种情况下,编写一个可以传递给
groupreduce
的函数非常简单,如下所示:

function vol_weighted_avg3(a,b)
    ap, av, bp, bv = a.price, a.volume, b.price, b.volume
    @NT(price=(ap*av + bp*bv)/(av+bv), volume=av+bv)
end
(唯一的缺点是,你会得到一列交易总量)

现在,让我们看看三个正在发挥作用的功能:

julia> srand(1);

julia> trades = table(rand(10^7), rand(10^7), rand(1:4, 10^7),
                      names=[:price,:volume,:date], pkey=:date);

julia> groupby(vol_weighted_avg, trades, :date)
Table with 4 rows, 2 columns:
date  vol_weighted_avg
──────────────────────
1     0.500097
2     0.499923
3     0.50013
4     0.499711

julia> groupby(vol_weighted_avg2, trades, :date)
Table with 4 rows, 2 columns:
date  vol_weighted_avg2
───────────────────────
1     0.500097
2     0.499923
3     0.50013
4     0.499711

julia> groupreduce(vol_weighted_avg3, trades, :date)
Table with 4 rows, 3 columns:
date  price     volume
─────────────────────────
1     0.500097  1.2482e6
2     0.499923  1.25025e6
3     0.50013   1.25168e6
4     0.499711  1.249e6
您可以检查它们的相对性能,以发现最后一个选项(使用
groupreduce
)速度更快且内存效率更高,即使对于内存中的数据:

julia> using BenchmarkTools

julia> @benchmark groupby($vol_weighted_avg, $trades, :date)
BenchmarkTools.Trial:
  memory estimate:  2.16 GiB
  allocs estimate:  105003042
  --------------
  minimum time:     3.301 s (15.41% GC)
  median time:      3.321 s (16.95% GC)
  mean time:        3.321 s (16.95% GC)
  maximum time:     3.341 s (18.47% GC)
  --------------
  samples:          2
  evals/sample:     1

julia> @benchmark groupby($vol_weighted_avg2, $trades, :date)
BenchmarkTools.Trial:
  memory estimate:  1.71 GiB
  allocs estimate:  85003045
  --------------
  minimum time:     2.689 s (15.23% GC)
  median time:      2.748 s (17.09% GC)
  mean time:        2.748 s (17.09% GC)
  maximum time:     2.807 s (18.88% GC)
  --------------
  samples:          2
  evals/sample:     1

julia> @benchmark groupreduce($vol_weighted_avg3, $trades, :date)
BenchmarkTools.Trial:
  memory estimate:  11.50 KiB
  allocs estimate:  254
  --------------
  minimum time:     103.955 ms (0.00% GC)
  median time:      106.777 ms (0.00% GC)
  mean time:        108.810 ms (0.00% GC)
  maximum time:     148.807 ms (0.00% GC)
  --------------
  samples:          47
  evals/sample:     1

这太完美了,谢谢!我的大部分问题都是因为不理解groupby函数返回的是什么,然后又不知道如何对命名的整数进行平均。我能够得到一个不同的解决方法,返回所需的结果,但我将尝试您的方法,并报告性能