2017-08-04 881 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

相关问题