【Pandas】文字列のラベルを自動で数値化するpd.factorize(文字列配列)
Pandasを使って、データのラベルを文字列から数値に変換する方法。pd.factorize(配列)
というメソッドを使います。凄い簡単便利。
実行環境
はじめに
機械学習ライブラリのsklearnに付属するデータセットの中に、アヤメの分類用データが入っています。正解ラベルはアヤメの種類が数値化されていたと思いますが、今回使っているアヤメのデータはネットからダウンロードしたもので、アヤメの種類名が文字列で表記してあった。
それを数値化するにはどうしたら良いかが今回の主旨です。
データの確認をします。
import pandas as pd fname = "iris.csv" #ネットからダウンロードしたデータ
# データcsvファイルを開く
df = pd.read_csv(fname)
df
sepal.length | sepal.width | petal.length | petal.width | variety | |
---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | Setosa |
1 | 4.9 | 3.0 | 1.4 | 0.2 | Setosa |
2 | 4.7 | 3.2 | 1.3 | 0.2 | Setosa |
3 | 4.6 | 3.1 | 1.5 | 0.2 | Setosa |
4 | 5.0 | 3.6 | 1.4 | 0.2 | Setosa |
... | ... | ... | ... | ... | ... |
145 | 6.7 | 3.0 | 5.2 | 2.3 | Virginica |
146 | 6.3 | 2.5 | 5.0 | 1.9 | Virginica |
147 | 6.5 | 3.0 | 5.2 | 2.0 | Virginica |
148 | 6.2 | 3.4 | 5.4 | 2.3 | Virginica |
149 | 5.9 | 3.0 | 5.1 | 1.8 | Virginica |
150 rows × 5 columns
一番右の列「variety」は文字列が入っている。
これを今回は数値化したい。どうやれば良いか。sklearn付属のデータは0,1,2と番号が割り振りしてあったはず。真似します。
その前に、「variety」列のユニークとその個数を見ておこう。
# ユニークな要素抽出 print(df.iloc[:,-1].unique()) # ユニークの個数 print(len((df.iloc[:,-1].unique()))) #または print(df.iloc[:, -1].nunique())
['Setosa' 'Versicolor' 'Virginica']
3
3
3種類の文字列。
文字列のカテゴリカルデータを数値化するpd.factorize(文字列の配列)
今回の目的です。
pandas.factorize()
を使うと
["a", "b", "c" ,"a"]
→[0, 1, 2, 0]
のように自動的に変換してくれるんですと。なんと便利。
簡単な例をやってから、データを変換してみます。適当なリストをつくり、それを数値化します。
# 文字列のリスト(適当 arr = " a b c d c a d".split() # 文字列データを数値に置き換え arr_int = pd.factorize(arr) # 表示 print(arr) print(arr_int)
['a', 'b', 'c', 'd', 'c', 'a', 'd']
(array([0, 1, 2, 3, 2, 0, 3]), array(['a', 'b', 'c', 'd'], dtype=object))
うおっ \(゜o゜;)/、簡単!
リストをpd.factorize()に渡しただけで出来た。
この調子で、アヤメの種類名ラベル列「variety」を数値化
# 文字列カテゴリーの表示 print(df.iloc[:, -1]) # 文字列カテゴリーを数値化する pd.factorize(df.iloc[:, -1])
0 Setosa
1 Setosa
2 Setosa
3 Setosa
4 Setosa
...
145 Virginica
146 Virginica
147 Virginica
148 Virginica
149 Virginica
Name: variety, Length: 150, dtype: object
(array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]),
Index(['Setosa', 'Versicolor', 'Virginica'], dtype='object'))
タプル型で要素が2つ入ったデータが返ってきました。凄い簡単。一応型などを確認。
data = pd.factorize(df.iloc[:,-1]) print(type(data)) print("="*30) print(data[0]) print("="*30) print(data[1])
<class 'tuple'>
==============================
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2]
==============================
Index(['Setosa', 'Versicolor', 'Virginica'], dtype='object')
データフレームの「variety」列をこの数値化データに入れ換えて今回は終わりにします。
# 文字列variety列を数値データに置換 df["variety"] = pd.factorize(df.iloc[: , -1])[0] # 表示 df
sepal.length | sepal.width | petal.length | petal.width | variety | |
---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | 0 |
1 | 4.9 | 3.0 | 1.4 | 0.2 | 0 |
2 | 4.7 | 3.2 | 1.3 | 0.2 | 0 |
3 | 4.6 | 3.1 | 1.5 | 0.2 | 0 |
4 | 5.0 | 3.6 | 1.4 | 0.2 | 0 |
... | ... | ... | ... | ... | ... |
145 | 6.7 | 3.0 | 5.2 | 2.3 | 2 |
146 | 6.3 | 2.5 | 5.0 | 1.9 | 2 |
147 | 6.5 | 3.0 | 5.2 | 2.0 | 2 |
148 | 6.2 | 3.4 | 5.4 | 2.3 | 2 |
149 | 5.9 | 3.0 | 5.1 | 1.8 | 2 |
150 rows × 5 columns
おわりに
正解ラベル カテゴリカルデータを数値化する際、今回やった方法とは別に「ダミー変数化」または「one hot エンコーディング」と呼ばれる手法があります。
今回はラベル3種類を数値化して0,1,2
と自動で割り振られましたが、これ等の数値の大小には本来は意味を持ちません。単に数値に置き換えているだけです。しかし機械学習は数値の大小には意味があるものとして測ってしまい、分類予測モデルの精度に関わってくる。
それを避ける為に正解ラベル カテゴリカルデータを0か1だけで表現する方法が「ダミー変数化」「one-hotエンコーディング」と呼ばれる手法、ということだそうです。
機械学習初心者向けのアヤメの分類では、主にsklearnのSVM(サポートベクターマシン)のLinearSVCという分類器などを使ったりして分類予測モデルを作りますが、その際、 正解ラベル(目的変数)はダミー変数化しません。単に数値化された正解ラベルで行う。なぜone-hot変数化する必要がないのか分かりません。一方でtensorflowを使っての分類では必要だという。この辺の違いは分類器の特徴の違いによるのでしょうけど。もう少し理解が要ります。
ダミー変数化についてはPandasで簡単にできますので、次でやることにします。
- 追記
こちらです→【Pandas】カテゴリカルデータのダミー変数化(one-hot)する pandas.get_dummies() - よちよちpython
以上です。