2017-08-04 300 views
1

DataFrame具有整數的兩列AB根據列條件交換列值(Pandas DataFrame)

a  b 
1  3 
4  2 
2  0 
6  1 
... 

我需要以如下方式來交換:

if df.a > df.b: 
    temp = df.b 
    df.b = df.a 
    df.a = temp 

預期輸出:

a  b 
1  3 
2  4 <---- 
0  2 <---- 
1  6 <---- 

基本上總是在列A具有二進制補碼的較小的值。

我覺得我應該使用loc但我找不到正確的方法。

回答

3

使用np.where你可以做

In [21]: df.a, df.b = np.where(df.a > df.b, [df.b, df.a], [df.a, df.b]) 

In [23]: df 
Out[23]: 
    a b 
0 1 3 
1 2 4 
2 0 2 
3 1 6 

或者,使用.loc

In [35]: cond = df.a > df.b 

In [36]: df.loc[cond, ['a', 'b']] = df.loc[cond, ['b', 'a']].values 

In [37]: df 
Out[37]: 
    a b 
0 1 3 
1 2 4 
2 0 2 
3 1 6 

或者.apply(np.sort, axis=1)如果你需要更小的a值和較大b

In [54]: df.apply(np.sort, axis=1) 
Out[54]: 
    a b 
0 1 3 
1 2 4 
2 0 2 
3 1 6 
4
In [443]: df['a'], df['b'] = df.min(axis=1), df.max(axis=1) 

In [444]: df 
Out[444]: 
    a b 
0 1 3 
1 2 4 
2 0 2 
3 1 6 

pd.DataFrame(np.sort(d.values, axis=1), d.index, d.columns) 
2

眼看着@JohnGait和@MaxU提出的方法,我做了一個小速度對比。

arr = np.random.randint(low = 100, size = (10000000, 2)) 

# using np.where 
df = pd.DataFrame(arr, columns = ['a', 'b']) 
t_0 = time.time() 
df.a, df.b = np.where(df.a > df.b, [df.b, df.a], [df.a, df.b]) 
t_1 = time.time() 

# using df.loc 
df = pd.DataFrame(arr, columns = ['a', 'b']) 
t_2 = time.time() 
cond = df.a > df.b 
df.loc[cond, ['a', 'b']] = df.loc[cond, ['b', 'a']].values 
t_3 = time.time() 

# using df.min 
df = pd.DataFrame(arr, columns = ['a', 'b']) 
t_4 = time.time() 
df['a'], df['b'] = df.min(axis=1), df.max(axis=1) 
t_5 = time.time() 

# using np.sort 
t_6 = time.time() 
df_ = pd.DataFrame(np.sort(arr, axis=1), df.index, df.columns) 
t_7 = time.time() 

t_1 - t_0 # using np.where: 5.759037971496582 
t_3 - t_2 # using .loc:  0.12156987190246582 
t_5 - t_4 # using df.min: 1.0503261089324951 
t_7 - t_6 # 0.20351791381835938  

儘管第二種方法是最快的方法,但實際收益並不重要。我出於學究原因在此添加它。我沒有包含排序方法,因爲我相信這會變慢很多。

編輯 我錯誤地報告了np.where的計算時間,這是由於我犯了一個錯誤。修正了(原來它的最慢很多的!),加上另一個方法(以下@ MaxU的評論)

+0

尼斯比較! +1。你可以爲'pd.DataFrame(np.sort(d.values,axis = 1),d.index,d.columns)'添加時間嗎? – MaxU

+1

@MaxU:補充說,也做了一個更正 –

+0

,因爲我正在處理大型數據集,這非常好! – csbr

3

解決方案
就這麼簡單

df.values.sort(1) 

df 

    a b 
0 1 3 
1 2 4 
2 0 2 
3 1 6 

發生了什麼
我可以使用sort方法對numpy.array進行排序。我傳遞參數axis=1以表明我想沿第一個軸排序(按行排序)。數據幀的values屬性訪問底層的numpy數組。所以df.values.sort(1)排序的基礎值排序明智......完成。


我們可以更明確一點與

df.values[:] = np.sort(df.values, 1) 

這使得我們很多的靈活性,在列的子集執行此或反向排序

df.values[:, ::-1] = np.sort(df.values, 1) 
+1

這太棒了! – MaxU

+0

@MaxU謝謝 – piRSquared

相關問題