2017-10-15 20 views
0

が、私はグループでの変数の平均値を計算するためにaggregate機能を使用しようとしていますと、Julia:IndexedTables.jlの集計を使ってグループごとに平均を計算する方法は?

私はエラーを取得する方法
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) 

が正常に動作します

答えて

1

編集:

res = IndexedTables.aggregate_vec(mean, DT, by=(:id1,), with=:v3) 

ヘルプから:

help?> IndexedTables.aggregate_vec 

aggregate_vec(::関数F、xは:: IndexedTable)を は、隣接コンバインベクトルからスカラーへの関数を使用して等しいインデックスを持つ行平均を意味する。


旧答え:それは私たちが望むような何かがうまくいかない場合は、ヘルパーのタイプと関数を作成する方法)私のために(楽しい運動であったため

(私はそれを維持します。将来的に誰かを助けることができるかもしれません:)


私はどのように平均を集めたいのですか?私のアイデアは、等質量の点の "重心"を計算することです。

2点の中心:G =(A + B)/ 2

(Gの質量は、Aの質量+ Bの質量であるため2G)(凝集)第三の点C(2G + C)である/ 3を添加

など

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 

(おそらく:P)
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 

そして今、それは私はあなたが集計平均は精度に影響を与えていることがわかり願ってい

res = IndexedTables.aggregate(mediocre, DT, by=(:id1,), with=:v3) 
id1  │ 
────────┼──────── 
"id001" │ 45.9404 
"id002" │ 47.0032 
"id003" │ 46.0846 
"id004" │ 47.2567 
... 

を作品! (より多くの和と除算演算があります)

0

私は本当にあなたを助けしたいと思いますが、それは私の10メートルを取りましたすべてのパッケージをインストールし、コードを実行して実際に何が実行されているか(または実行されていないか)を数分で確認します。あなたが問題に焦点を当てた「最小限の作業例」を提供すれば素晴らしいでしょう。実際、問題を再現する唯一の要件は、一見IndexedTablesと2つのランダム配列です。とにかく

(申し訳ありませんが、これは完全な答えはありませんが、コメントであるには余りにも長い。)

、あなたがIndexedTables.aggregateのドキュメンテーション文字列を読めば、あなたはそれが明らかに二つの引数をとり、機能を必要としていることがわかり単一の値::あなたは私はあなたが関数expかわからないので

no method matching mean(::Float64, ::Float64) 

があることを、あなたが投稿エラーメッセージに表示さ

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. 

を返します。計算するために、私は今あなたが2つの数字のmeanの値を計算したいと仮定します。この場合、あなたはmean()のための別の方法を定義することができます。

Base.mean(x, y) = (x+y)/2 

これはaggregate機能の署名要件を満たします。しかし、これがあなたが望むものなのかどうかはわかりません。

1

あなたはどのように一つに二つの数を減らすために、それを指示する必要があります。 meanは配列用です。だから無名関数を使用します。

res = IndexedTables.aggregate((x,y)->(x+y)/2, DT, by=(:id1,), with=:v3) 
+1

私はOPが望んでいないことを確信しています - 私は彼がv3によって与えられたすべてのグループのv3値の平均を望んでいると思う - つまり、 'tapply(DT $ v3、DT $ id1、mean) 'Rで; dataFrames内のgroupby(DT、:id1)]のsubdfの '[mean(subdf [:v3]) 'です。 –

+1

私はジュリアにtapplyを持っていたいと思う(私はそれがRLEVectors.jlであることを知っているが、それは少しclunky感じている) –

+1

@ MichaelK.Borregaardはい私はグループによって値の平均を取ることについて考えている。 – xiaodai

関連する問題