2017-10-16 94 views
2

如何將pandas 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 

我可以使用使用factorize成功地爲一列:

df['A_ID'] = pd.factorize(df.A)[0] 

我怎麼能做到這一點一致跨兩列的值的映射?我是否需要求助於使用自定義的lambda函數,或者是否有辦法通過factorize來完成此操作?

回答

1

pd.factorizeapply + 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 
+1

我喜歡在此解決方案中使用numpy重塑。+1 –

+0

@ScottBoston帶着興趣返回:-) –

+1

你可以做'df.values.ravel('F')''df.values.T.reshape(-1,)'inplace'以及 – Zero

1

這裏有一種方法,如果你想重用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 

或者,使用replace

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} 
+0

感謝@Zero,這適用於我原來的問題,其中在B列的所有值也出現在A列中我更新的問題,其中塔B一個不在列A中的值。我該如何解決這種情況?目前,在這種情況下'B_ID'將返回'NaN',因爲該值不存在於「事實」中。另外,在我的系統中,「B_ID」值回到了雙倍(4.0,0.0,...)。在這個過程中我如何將它們轉換爲int,以匹配'A_ID'? –

2

讓我們用applyadd_suffixpd.factorizeassign

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 

輸出繼電器用更新的數據集:

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