julia - 用于 JuliaDB 的自定义 GroupBy 函数
问题描述
我正在使用 JuliaDB 函数读取一些股票交易数据loadtable
,我想对所有相同的日期进行分组并应用自定义函数。
自定义函数旨在获取同一日期的一组交易并返回单笔交易,交易量为总和,交易价格为交易量加权平均值。我可以得到交易量的总和,但我很难获得交易量加权平均值。
function vol_weighted_avg(x)
return (x.price .* x.volume) / sum(x.volume)
end
这是功能,但不适用于
groupby(vol_weighted_avg, trades, :date)
我花了很长时间与 groupby 一起玩,但我无法弄清楚,也没有遇到说明如何执行上述操作的文档。
解决方案
您的代码有几个问题。我的答案是 Julia 0.6 和 JuliaDB 0.8.4。您必须了解的是,它groupby
返回 s 的向量NamedTuple
。因此,实现您的功能的最简单方法是:
vol_weighted_avg(x) =
sum(getindex.(x, :price) .* getindex.(x,:volume)) / sum(getindex.(x,:volume))
您可以使用mean
fromStatsBase
来实现相同的目的:
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
推荐阅读
- laravel - 在 AWS Elastic Beanstalk 上安装 composer 时出错
- c++ - 如何使用模板制作 3D 对象的打印版本?(c++)
- flutter - 在 AlertDialogue 中显示的 RadioListTile 列表中更新选择的问题
- z3 - 如何在 z3py 中连接正则表达式?
- discord - awaitReactions 遇到问题
- python - 使用 Functions Framework for Python 时如何在 Google Cloud Buildpacks 中设置运行时版本?
- algorithm - 二进制搜索以查找布尔数组中的最高真实索引
- prisma - 生成迁移 README 时,Prisma 的名字来自哪里?
- swift - 快速为牛津词典 API 构建数据模型的问题
- google-cloud-platform - 在特定域上执行 cloud_api web_detection 搜索