それが起こったのは,たぶん 2022 年 1 月末のある日。
以前にはなんのエラーもなく実行できていたプログラムでエラーが生じる。FreqTables.freqtable() で作成したクロス集計表の列や行を抽出できなくなっていた。
再現すると以下のようである。
まず以下のようなデータを読む。
io = IOBuffer("""
ID,Weight,Height,Age,BloodType,Gender
125,44.6,157.6,17,A,Male
321,57.3,158.8,26,B,Male
437,54.3,162.2,22,AB,Female
426,45.4,160.8,31,O,Male
243,48.5,174.5,34,B,Female
""")
CSV.read() の第 1 引数は IOBuffer() の戻り値をとることができる。
using CSV, DataFrames
df = CSV.read(io, DataFrame)
もう気づいてしまった人もいるかもしれないが,先に進む。
df.Gender と df.BloodType のクロス集計表を作る。
using FreqTables
tbl = freqtable(df.Gender, df.BloodType)
2×4 Named Matrix{Int64}
Dim1 ╲ Dim2 │ "A" "AB" "B" "O"
────────────┼───────────────────────
"Female" │ 0 1 1 0
"Male" │ 1 0 1 1
集計表 tbl の 1 行目,2 列目を取り出してみる。
以下はいずれもエラーになる。
MethodError: no method matching indices(::OrderedCollections.OrderedDict{String7, Int64}, ::String)
tbl["Female", :]
tbl[:, "AB"]
以下はなんの問題もない。
tbl[1, :]
4-element Named Vector{Int64}
Dim2 │
──────┼──
"A" │ 0
"AB" │ 1
"B" │ 1
"O" │ 0
tbl[:, 2]
2-element Named Vector{Int64}
Dim1 │
─────────┼──
"Female" │ 1
"Male" │ 0
あれこれやって,半日が過ぎた(大げさ)。
幸い,以前実行した結果が残っているので,ダメ元で今の出力結果と比較した。
気がついた。
BloodType と Gender の型が String3 と String7 になっている。
今までは両方とも String だった。
BloodType と Gender の型を String に変換しよう。
df[!, :BloodType] = string.(df.BloodType)
df[!, :Gender] = string.(df.Gender)
df
これでもう一度集計表を作り,行と列を取り出してみよう。
tbl = freqtable(df.Gender, df.BloodType)
2×4 Named Matrix{Int64}
Dim1 ╲ Dim2 │ A AB B O
────────────┼───────────────
Female │ 0 1 1 0
Male │ 1 0 1 1
tbl["Female", :]
4-element Named Vector{Int64}
Dim2 │
──────┼──
A │ 0
AB │ 1
B │ 1
O │ 0
tbl[1, :]
4-element Named Vector{Int64}
Dim2 │
──────┼──
A │ 0
AB │ 1
B │ 1
O │ 0
tbl[:, "AB"]
2-element Named Vector{Int64}
Dim1 │
───────┼──
Female │ 1
Male │ 0
tbl[:, 2]
2-element Named Vector{Int64}
Dim1 │
───────┼──
Female │ 1
Male │ 0
前と同じようにちゃんと動いている。
そもそも String3 と String7 とはなんぞやと,ぐぐってみると以下のようなことがわかった。
・ 固定長文字列(Fixed width strings) ということで,String1, String3, String7, ..., String(2^8-1) がある。
・ かなり前からあるが,CSV.jl 0.9.1 ではすでに取り込まれていた。2022/02/03 では CSV v0.10.2 だ。
・ パフォーマンスが優れている。
・ まだサポートしていないパッケージがある。まさに freqtable() がそうだった。
そのうちに freqtable() も固定長文字列に対応するのだろうか。
※コメント投稿者のブログIDはブログ作成者のみに通知されます