Python 使用一致映射跨数据帧列分解值
如何对跨两列存在的值使用pandasPython 使用一致映射跨数据帧列分解值,python,pandas,dataframe,categories,Python,Pandas,Dataframe,Categories,如何对跨两列存在的值使用pandasfactorize 具体来说,我尝试将两列中存在的值转换为数值,并将相应的分解值放入新列中,以便分解与两个输入列“A”和“B”一致 现有数据帧: A B 0 a b 1 c a 2 d a 3 e c 4 c b 5 b e 6 e f 期望输出: A B A_ID B_ID 0 a b 0 4 1 c a 1
factorize
具体来说,我尝试将两列中存在的值转换为数值,并将相应的分解值放入新列中,以便分解与两个输入列“A”和“B”一致
现有数据帧:
A B
0 a b
1 c a
2 d a
3 e c
4 c b
5 b e
6 e f
期望输出:
A B A_ID B_ID
0 a b 0 4
1 c a 1 0
2 d a 2 0
3 e c 3 1
4 c b 1 4
5 b e 4 3
6 e f 3 5
我能够使用以下方法成功地对一列使用因子分解
:
df['A_ID'] = pd.factorize(df.A)[0]
如何通过跨两列的值的一致映射来实现这一点?我是否需要转而使用自定义的
lambda
函数,或者是否有一种方法可以通过factorize
实现这一点?如果您想重用factorize值,这里有一种方法
In [2637]: facts = np.unique(np.unique(df[['A', 'B']]), return_index=True)
In [2638]: mapping = dict(zip(*facts))
In [2639]: df.join(df[['A', 'B']].apply(lambda x: x.map(mapping)).add_suffix('_ID'))
Out[2639]:
A B A_ID B_ID
0 a b 0 1
1 c a 2 0
2 d a 3 0
3 e c 4 2
4 c b 2 1
5 b e 1 4
6 e f 4 5
或,使用
替换
In [2640]: df.join(df[['A', 'B']].replace(mapping).add_suffix('_ID'))
Out[2640]:
A B A_ID B_ID
0 a b 0 1
1 c a 2 0
2 d a 3 0
3 e c 4 2
4 c b 2 1
5 b e 1 4
6 e f 4 5
而且,为了保留您的价值顺序,请使用
In [2]: mapping = dict(zip(*pd.factorize(df['A'].append(df['B']).drop_duplicates())[::-1]))
In [2]: mapping
Out[2666]: {'a': 0, 'b': 4, 'c': 1, 'd': 2, 'e': 3, 'f': 5}
In [3]: df.join(df[['A', 'B']].replace(mapping).add_suffix('_ID'))
Out[3]:
A B A_ID B_ID
0 a b 0 4
1 c a 1 0
2 d a 2 0
3 e c 3 1
4 c b 1 4
5 b e 4 3
6 e f 3 5
详细信息
In [2641]: facts
Out[2641]:
(array(['a', 'b', 'c', 'd', 'e', 'f'], dtype=object),
array([0, 1, 2, 3, 4, 5], dtype=int64))
In [2642]: mapping
Out[2642]: {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5}
让我们使用apply
,add_suffix
和pd.factorize
和assign
:
f = pd.factorize(df.stack().drop_duplicates().sort_index(level=1))
s1 = pd.Series(f[0], index=f[1])
print(df.assign(**df.apply(lambda x: x.map(s1)).add_suffix('_ID')))
输出:
A B A_ID B_ID
0 a b 0 1
1 c a 2 0
2 d a 3 0
3 e c 4 2
4 c b 2 1
5 b e 1 4
具有更新数据集的输出:
pd.factorize
,apply
+pd.Categorical
:
_, b = pd.factorize(df.values.T.reshape(-1, ))
# or df.values.ravel('F'), as suggested by Zero
r = df.apply(lambda x: pd.Categorical(x, b).codes).add_suffix('_ID')
A_ID B_ID
0 0 4
1 1 0
2 2 0
3 3 1
4 1 4
5 4 3
6 3 5
pd.concat([df, r], 1)
A B A_ID B_ID
0 a b 0 4
1 c a 1 0
2 d a 2 0
3 e c 3 1
4 c b 1 4
5 b e 4 3
6 e f 3 5
感谢@Zero,这适用于我的原始问题,其中B列中的所有值也出现在A列中。我更新了B列中有一个不在A列中的值的问题。我如何解决这种情况?目前,在这种情况下,B_ID
将返回NaN
,因为该值在facts
中不存在。另外,在我的系统上,B_ID
值以双倍(4.0,0.0,…)的形式返回。在这个过程中,如何将它们转换为int,以匹配A_ID
?我喜欢在这个解决方案中使用numpy整形+1@ScottBoston感兴趣地返回:-)您可以使用df.values.ravel('F')
代替df.values.T.restrape(-1,)
aswell@Zero真漂亮!谢谢:-)谢谢@cᴏʟᴅsᴘᴇᴇᴅ, 这很有效。我用一个额外的列“C”更新了这个问题。因此,当我在解决方案的第1行和第2行中使用df[['A','B']]
而不是df
来解释并在数据框中包含这个额外的列“C”时,这对我来说是有效的。这是解决这个问题的最佳方法吗?
_, b = pd.factorize(df.values.T.reshape(-1, ))
# or df.values.ravel('F'), as suggested by Zero
r = df.apply(lambda x: pd.Categorical(x, b).codes).add_suffix('_ID')
A_ID B_ID
0 0 4
1 1 0
2 2 0
3 3 1
4 1 4
5 4 3
6 3 5
pd.concat([df, r], 1)
A B A_ID B_ID
0 a b 0 4
1 c a 1 0
2 d a 2 0
3 e c 3 1
4 c b 1 4
5 b e 4 3
6 e f 3 5