ジュリアで周波数を計算する方法
概要 1
FreqTables.jl
パッケージのfreqtable()
関数を使えばいい。Rのfreq()
関数と似た機能を持っている。
コード
配列
julia> compartment = rand(['S','I','R'], 1000);
julia> freqtable(compartment)
3-element Named Vector{Int64}
Dim1 │
──────┼────
'I' │ 316
'R' │ 342
'S' │ 342
上記のように配列を入れると、各階級ごとにカウントしてくれる。
データフレーム
freqtable()
は特にデータフレームに便利だ。Rでの質的変数を含む回帰分析の例と同様に、組み込みデータToothGrowth
を読み込んでみよう。
julia> ToothGrowth = dataset("datasets", "ToothGrowth")
60×3 DataFrame
Row │ Len Supp Dose
│ Float64 Cat… Float64
─────┼────────────────────────
1 │ 4.2 VC 0.5
2 │ 11.5 VC 0.5
3 │ 7.3 VC 0.5
4 │ 5.8 VC 0.5
⋮ │ ⋮ ⋮ ⋮
58 │ 27.3 OJ 2.0
59 │ 29.4 OJ 2.0
60 │ 23.0 OJ 2.0
53 rows omitted
julia> freqtable(ToothGrowth, :Len)
43-element Named Vector{Int64}
Len │
─────┼──
4.2 │ 1
5.2 │ 1
5.8 │ 1
6.4 │ 1
⋮ ⋮
29.5 │ 1
30.9 │ 1
32.5 │ 1
33.9 │ 1
julia> freqtable(ToothGrowth, :Supp)
2-element Named Vector{Int64}
Supp │
──────┼───
"OJ" │ 30
"VC" │ 30
julia> freqtable(ToothGrowth, :Dose)
3-element Named Vector{Int64}
Dose │
──────┼───
0.5 │ 20
1.0 │ 20
2.0 │ 20
ToothGrowth
は、ビタミンCまたはオレンジジュース:Supp
を異なる量:Dose
で餌として与えられたモルモットの歯の長さ:Len
を記録したデータだ。各カラムごとに頻度を計算すると、上記のようにきれいに整理される。ここで、データが必ずしもカテゴリカルデータである必要はないことが確認できる。
julia> freqtable(ToothGrowth, :Supp, :Dose)
2×3 Named Matrix{Int64}
Supp ╲ Dose │ 0.5 1.0 2.0
────────────┼──────────────
"OJ" │ 10 10 10
"VC" │ 10 10 10
もちろん、このようなテーブルはカテゴリカルデータを扱う時に最も効果的だ。:Supp
, :Dose
に対する頻度を計算すると、自動的に2次元にカテゴリを分けて頻度を計算してくれた。
julia> freqtable(ToothGrowth, :Len, :Dose, :Supp)
43×3×2 Named Array{Int64, 3}
[:, :, Supp="OJ"] =
Len ╲ Dose │ 0.5 1.0 2.0
───────────┼──────────────
4.2 │ 0 0 0
⋮ ⋮ ⋮ ⋮
33.9 │ 0 0 0
[:, :, Supp="VC"] =
Len ╲ Dose │ 0.5 1.0 2.0
───────────┼──────────────
4.2 │ 1 0 0
⋮ ⋮ ⋮ ⋮
33.9 │ 0 0 1
3つ以上のカラムに対する計算は、ただの2次元テーブルを階級の数だけリターンする。この辺りになると、データを探索したり要約する意味はほとんどなくなる。
性能比較
julia> @time for t in 1:10^4
freqtable(compartment)
end
@time for t in 1:10^4
count(compartment .== 'S')
count(compartment .== 'I')
count(compartment .== 'R')
end
0.068229 seconds (340.00 k allocations: 27.466 MiB)
0.059198 seconds (180.00 k allocations: 134.125 MiB, 36.71% gc time)
テーブルを離れて、頻度数の計算自体が有用だと思われる。直接カウントすることとfreqtable()
を通じて一度に頻度数を計算する速度を色々と計測してみたけど、どちらかが必ずしも速かったわけではなかった。データの量や階級の数によって、その都度前後したが、全体的にfreqtable()
が遅い傾向にあった。それでも大きく遅れを取るわけではないので、速度を考慮に入れずに、使うときはよく考えて使おう。
全コード
using FreqTables
compartment = rand(['S','I','R'], 1000);
freqtable(compartment)
using RDatasets
ToothGrowth = dataset("datasets", "ToothGrowth")
freqtable(ToothGrowth, :Len)
freqtable(ToothGrowth, :Supp)
freqtable(ToothGrowth, :Dose)
freqtable(ToothGrowth, :Supp, :Dose)
freqtable(ToothGrowth, :Len, :Dose, :Supp)
@time for t in 1:10^4
freqtable(compartment)
end
@time for t in 1:10^4
count(compartment .== 'S')
count(compartment .== 'I')
count(compartment .== 'R')
end
環境
- OS: Windows
- julia: v1.6.3
- FreqTables v0.4.5