logo

ジュリアで周波数を計算する方法 📂ジュリア

ジュリアで周波数を計算する方法

概要 1

FreqTables.jlパッケージのfreqtable()関数を使えばいい。Rfreq()関数と似た機能を持っている。

コード

配列

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