使用一行来交换pandas数据框中所选行的列值的正确语法是什么?

sta*_*yra 18 python pandas

我使用pandas版本0.14.1与Python 2.7.5,我有一个包含三列的数据框,例如:

import pandas as pd

d = {'L':  ['left', 'right', 'left', 'right', 'left', 'right'],
     'R': ['right', 'left', 'right', 'left', 'right', 'left'],
     'VALUE': [-1, 1, -1, 1, -1, 1]}
df = pd.DataFrame(d)

idx = (df['VALUE'] == 1)
Run Code Online (Sandbox Code Playgroud)

得到一个如下所示的数据框:

       L      R  VALUE
0   left  right     -1
1  right   left      1
2   left  right     -1
3  right   left      1
4   left  right     -1
5  right   left      1
Run Code Online (Sandbox Code Playgroud)

对于行VALUE == 1,我想交换左右列的内容,以便所有"左"值最终在"L"列下,"右"值最终在"R"下柱.

已经定义了idx上面的变量,通过使用临时变量,我可以在另外三行中轻松完成此操作,如下所示:

tmp = df.loc[idx,'L']
df.loc[idx,'L'] = df.loc[idx,'R']
df.loc[idx,'R'] = tmp
Run Code Online (Sandbox Code Playgroud)

然而,这对我来说似乎是非常笨拙和不雅的语法; 肯定熊猫支持更简洁的东西?我注意到如果我将输入中的列顺序交换到数据框.loc属性,那么我得到以下交换输出:

In [2]: print(df.loc[idx,['R','L']])
      R      L
1  left  right
3  left  right
5  left  right
Run Code Online (Sandbox Code Playgroud)

这告诉我,通过使用以下单行,我应该能够实现与上面相同的交换:

df.loc[idx,['L','R']] = df.loc[idx,['R','L']]
Run Code Online (Sandbox Code Playgroud)

然而,当我实际尝试这个时,没有任何反应 - 列保持未被破坏.就好像pandas会自动识别我在赋值语句的右侧以错误的顺序放置列,并自动纠正问题.有没有办法可以在pandas赋值语句中禁用这个"列顺序自动更正",以便在不创建不必要的临时变量的情况下实现交换?

DSM*_*DSM 25

一种避免列名对齐的方法是通过以下方式下拉到底层数组.values:

In [33]: df
Out[33]: 
       L      R  VALUE
0   left  right     -1
1  right   left      1
2   left  right     -1
3  right   left      1
4   left  right     -1
5  right   left      1

In [34]: df.loc[idx,['L','R']] = df.loc[idx,['R','L']].values

In [35]: df
Out[35]: 
      L      R  VALUE
0  left  right     -1
1  left  right      1
2  left  right     -1
3  left  right      1
4  left  right     -1
5  left  right      1
Run Code Online (Sandbox Code Playgroud)

  • 这似乎只有在系列 _idx_ 具有 dtype _bool_ 时才能正常工作。如果您的系列的值为 0/1 而不是 True/False,请使用“idx.astype(bool)”转换为 dtype _bool_。 (3认同)

Joh*_*hnE 7

这里要注意的关键是,pandas 尝试使用索引和列名自动对齐行和列。因此,您需要以某种方式告诉熊猫忽略此处的列名。一种方法是 @DSM 所做的,通过转换为 numpy 数组。另一种方法是重命名列:

>>> df.loc[idx] = df.loc[idx].rename(columns={'R':'L','L':'R'})

      L      R  VALUE
0  left  right     -1
1  left  right      1
2  left  right     -1
3  left  right      1
4  left  right     -1
5  left  right      1
Run Code Online (Sandbox Code Playgroud)


Flo*_*oor 7

您也可以使用 ie 执行np.selectdf.where操作

选项1np.select

df[['L','R']] = pd.np.select(df['VALUE'] == 1, df[['R','L']].values, df[['L','R']].values)
Run Code Online (Sandbox Code Playgroud)

选项 2df.where

df[['L','R']] = df[['R','L']].where(df['VALUE'] == 1, df[['L','R']].values)
Run Code Online (Sandbox Code Playgroud)

选项 3df.mask

df[['L','R']] = df[['L','R']].mask( df['VALUE'] == 1, df[['R','L']].values)
Run Code Online (Sandbox Code Playgroud)

输出:

    L      R  VALUE
0  left  right     -1
1  left  right      1
2  left  right     -1
3  left  right      1
4  left  right     -1
5  left  right      1
Run Code Online (Sandbox Code Playgroud)