我正在尝试使用aggregate
函数按组计算变量的平均值
using Distributions, PooledArrays
N=Int64(2e9/8); K=100;
pool = [@sprintf "id%03d" k for k in 1:K]
pool1 = [@sprintf "id%010d" k for k in 1:(N/K)]
function randstrarray(pool, N)
PooledArray(PooledArrays.RefArray(rand(UInt8(1):UInt8(K), N)), pool)
end
using JuliaDB
DT = IndexedTable(Columns([1:N;]), Columns(
id1 = randstrarray(pool, N),
v3 = rand(round.(rand(Uniform(0,100),100),4), N) # numeric e.g. 23.5749
));
res = IndexedTables.aggregate(mean, DT, by=(:id1,), with=:v3)
我是如何得到错误的
MethodError: no method matching mean(::Float64, ::Float64)
Closest candidates are:
mean(!Matched::Union{Function, Type}, ::Any) at statistics.jl:19
mean(!Matched::AbstractArray{T,N} where N, ::Any) where T at statistics.jl:57
mean(::Any) at statistics.jl:34
in at base\<missing>
in #aggregate#144 at IndexedTables\src\query.jl:119
in aggregate_to at IndexedTables\src\query.jl:148
然而
IndexedTables.aggregate(+ , DT, by=(:id1,), with=:v3)
工作正常
答案 0 :(得分:1)
您需要告诉它如何将两个数字减少为一个。 mean
用于数组。所以只需使用匿名函数:
res = IndexedTables.aggregate((x,y)->(x+y)/2, DT, by=(:id1,), with=:v3)
答案 1 :(得分:1)
修改强>
res = IndexedTables.aggregate_vec(mean, DT, by=(:id1,), with=:v3)
来自帮助:
help?> IndexedTables.aggregate_vec
aggregate_vec(f :: Function,x :: IndexedTable) 使用从向量到标量的函数将具有相等索引的相邻行组合,例如。意味着强>
旧回答:
(我保留它是因为这是一个愉快的运动(对我而言)如果某些东西不能像我们想要的那样创建帮助器类型和功能。也许它可以在将来帮助某人:)
我不确定你喜欢如何聚合均值。我的想法是计算等效质量点的“重心”。
两点的中心:G =(A + B)/ 2
添加(聚合)第三点C是(2G + C)/ 3(2G,因为G的质量是A的质量+ B的质量)
等
struct Atractor
center::Float64
mass::Int64
end
" two points create new atractor with double mass "
mediocre(a::Float64, b::Float64) = Atractor((a+b)/2, 2)
# pls forgive me function's name! :)
" aggregate new point to atractor "
function mediocre(a::Atractor, b::Float64)
mass = a.mass + 1
Atractor((a.center*a.mass+b)/mass, mass)
end
测试:
tst_array = rand(Float64, 100);
isapprox(mean(tst_array), reduce(mediocre, tst_array).center)
true # at least in my tests! :)
mean(tst_array) == reduce(mediocre, tst_array).center # sometimes true
对于聚合函数,我们需要更多的工作:
import Base.convert
" we need method for convert Atractor to Float64 because aggregate
function wants to store result in Float64 "
convert(Float64, x::Atractor) = x.center
现在它(可能是:P)正常工作
res = IndexedTables.aggregate(mediocre, DT, by=(:id1,), with=:v3)
id1 │
────────┼────────
"id001" │ 45.9404
"id002" │ 47.0032
"id003" │ 46.0846
"id004" │ 47.2567
...
我希望你看到聚合均值对精度有影响! (有更多的和和除法运算)
答案 2 :(得分:0)
我真的很乐意帮助你,但我花了10分钟安装所有软件包,再过几分钟来运行代码并弄清楚它实际上做了什么(或没有)。如果您提供一个专注于问题的“最小工作示例”,那将是很棒的。实际上,重现问题的唯一要求是看似IndexedTables
和两个随机数组。
(对不起,这不是一个完整的答案,但要评论太久了。)
无论如何,如果你阅读IndexedTables.aggregate
的文档字符串,你会发现它需要一个带有两个参数的函数,显然会返回一个值::
help?> IndexedTables.aggregate
aggregate(f::Function, arr::IndexedTable)
Combine adjacent rows with equal indices using the given 2-argument
reduction function, returning the result in a new array.
您在发布的错误消息中看到
no method matching mean(::Float64, ::Float64)
由于我不知道您期望计算什么,我现在假设您要计算两个数字的mean
值。在这种情况下,您可以为mean()
定义另一种方法:
Base.mean(x, y) = (x+y) / 2
这将满足aggregate
函数签名要求。但我不确定这是不是你想要的。