pandas.factorize
函数将输入值编码为枚举类型或分类变量。
但是我如何轻松高效地转换数据帧的多个列呢?那么反向映射步骤呢?
示例:该数据帧包含具有字符串值的列,例如 "type 2",我想将它们转换为数字值,并可能稍后将它们翻译回来。
pandas.factorize
函数将输入值编码为枚举类型或分类变量。
但是我如何轻松高效地转换数据帧的多个列呢?那么反向映射步骤呢?
示例:该数据帧包含具有字符串值的列,例如 "type 2",我想将它们转换为数字值,并可能稍后将它们翻译回来。
如果您需要单独对每列进行因式分解,可以使用apply
:
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
通过dict
,可以使用map
将它们翻译回来,您需要使用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://dev59.com/QmUo5IYBdhLWcg3w2CaJ#20051631
我想从 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
...
def categorise(df):
categories = {k: v for v, k in enumerate(df.stack().unique())}
return df.replace(categories)
相比@jezrael的示例,性能略逊,但更易于阅读。此外,对于更大的数据集,它可能会升级得更好。如果有人感兴趣,我可以进行一些适当的测试。
df = df.select_dtypes(object)
? - jezrael