pandas.factorize
は、入力値を列挙型またはカテゴリ変数としてエンコードします。
しかし、データフレームの多くの列を簡単かつ効率的に変換するにはどうすればよいですか?逆マッピング手順はどうですか?
例:このデータフレームには、「type 2」などの文字列値が含まれる列が含まれます。これらの列を数値に変換し、後で変換することもできます。
各列を個別にapply
する必要がある場合は、factorize
を使用できます。
df = pd.DataFrame({'A':['type1','type2','type2'],
'B':['type1','type2','type3'],
'C':['type1','type3','type3']})
print (df)
A B C
0 type1 type1 type1
1 type2 type2 type3
2 type2 type3 type3
print (df.apply(lambda x: pd.factorize(x)[0]))
A B C
0 0 0 0
1 1 1 1
2 1 2 1
同じ文字列値に同じ数値が必要な場合:
print (df.stack().rank(method='dense').unstack())
A B C
0 1.0 1.0 1.0
1 2.0 2.0 3.0
2 2.0 3.0 3.0
一部の列にのみ関数を適用する必要がある場合は、サブセットを使用します。
df[['B','C']] = df[['B','C']].stack().rank(method='dense').unstack()
print (df)
A B C
0 type1 1.0 1.0
1 type2 2.0 3.0
2 type2 3.0 3.0
factorize
を使用したソリューション:
stacked = df[['B','C']].stack()
df[['B','C']] = pd.Series(stacked.factorize()[0], index=stacked.index).unstack()
print (df)
A B C
0 type1 0 0
1 type2 1 2
2 type2 2 2
map
by dict
を使用して、元に戻すことができます。この場合、 drop_duplicates
:
vals = df.stack().drop_duplicates().values
b = [x for x in df.stack().drop_duplicates().rank(method='dense')]
d1 = dict(Zip(b, vals))
print (d1)
{1.0: 'type1', 2.0: 'type2', 3.0: 'type3'}
df1 = df.stack().rank(method='dense').unstack()
print (df1)
A B C
0 1.0 1.0 1.0
1 2.0 2.0 3.0
2 2.0 3.0 3.0
print (df1.stack().map(d1).unstack())
A B C
0 type1 type1 type1
1 type2 type2 type3
2 type2 type3 type3
また、この回答は非常に有用であることがわかりました: https://stackoverflow.com/a/20051631/4643212
Pandas DataFrame( 'SrcIP'という名前のIPアドレスのリスト)の既存の列から値を取得し、新しい列( 'ID'という名前のこの例)。
解決:
df['ID'] = pd.factorize(df.SrcIP)[0]
結果:
SrcIP | ID
192.168.1.112 | 0
192.168.1.112 | 0
192.168.4.118 | 1
192.168.1.112 | 0
192.168.4.118 | 1
192.168.5.122 | 2
192.168.5.122 | 2
...
私の答えをリダイレクトしたい: https://stackoverflow.com/a/32011969/1694714
古い答え
結果のDataFrame全体でカテゴリの一貫性を保ちたい場合、この問題の別の読み取り可能なソリューションは、replaceを使用しています。
def categorise(df):
categories = {k: v for v, k in enumerate(df.stack().unique())}
return df.replace(categories)
@jezraelの例よりもパフォーマンスはわずかに劣りますが、読みやすくなっています。また、大規模なデータセットの方がエスカレートしやすい場合があります。誰かが興味を持っている場合、適切なテストを行うことができます。