根据列条件交换列值(Pandas DataFrame)

时间:2017-08-04 10:26:55

标签: python pandas

DataFrame有两列AB整数。

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,但我找不到正确的方法。

4 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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

答案 2 :(得分:3)

看到@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的评论)

答案 3 :(得分:3)

<强>解决方案
它就像

一样简单
numpy.array

发生了什么
我可以使用sort方法对axis=1进行排序。我传递参数values以表示我想沿第一个轴排序(按行方向)。数据帧的numpy属性访问基础df.values.sort(1)数组。所以df.values[:] = np.sort(df.values, 1) 按行排序......完成基础值。

我们可以用

更明确一些
df.values[:, ::-1] = np.sort(df.values, 1)

这使我们可以灵活地在列子集上执行此操作或反向排序

L <- list(cbind(b = 10), 
  cbind(a = 1:2, b = 2:3))

library(data.table)
rbindlist(lapply(L, as.data.table), fill = TRUE)
#    b  a
#1: 10 NA
#2:  2  1
#3:  3  2