この記事は、Elixir Advent Calendar 2024 シリーズ3 の7日目です
【本コラムは、10分で読め、5分で試せます】
piacere です、ご覧いただいてありがとございます
get_dummies①のコラム では、通番による数値化を行いましたが、値のバリエーションごとに列生成するpandasのget_dummiesと全く同じ仕様に改造してみましょう
たとえば、下記マップリストのc1/c3キーをダミー値処理すると、下記の結果のように、c1/c3の値のバリエーションが列生成された上で0か1かの数値化されます
maplist = [
%{"c1" => "v1", "c2" => 2, "c3" => true},
%{"c1" => "v1", "c2" => 5, "c3" => false}
]
keys = ["c1", "c3"]
結果:[
%{"c1_v1" => 1, "c1_v2" => 0, "c2" => 2, "c3_true" => 1, "c3_false" => 0},
%{"c1_v1" => 0, "c1_v2" => 1, "c2" => 5, "c3_true" => 0, "c3_false" => 1}
]
これを実装すると、こんなコードになります
maplist = [
%{"c1" => "v1", "c2" => 2, "c3" => true},
%{"c1" => "v2", "c2" => 5, "c3" => false}
]
keys = ["c1", "c3"]
Enum.reduce(keys, maplist, fn key, acc ->
uniqs =
Enum.map(maplist, & &1[key])
|> Enum.uniq
acc
|> Enum.map(fn map ->
Enum.reduce(uniqs, map, & Map.put(&2, "#{key}_#{&1}",
if map[key] == &1 do 1 else 0 end
) |> Map.delete(key))
end)
end)
結果:[
%{"c1_v1" => 1, "c1_v2" => 0, "c2" => 2, "c3_true" => 1, "c3_false" => 0},
%{"c1_v1" => 0, "c1_v2" => 1, "c2" => 5, "c3_true" => 0, "c3_false" => 1}
]
コード解説ですが、全体としては、ダミー値処理を各キーごとに行い、ダミー値化した結果をaccに積み続けるところまでは、get_dummies①と同じです
最初に、各キーごとに、カテゴリ値に値のバリエーションをEnum.uniqでユニーク化したものを、下記のように uniqs
として保持します
c1分
uniqs = ["v1", "v2"]
c3分
uniqs = [false, true]
次に、Enum.mapでマップリストを回し、各マップをMap.putを使って列生成し、元の値に合わせたダミー値の割り当てを行い、マップ更新しつつ、元のキー/値をマップから削除します