我正在使用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)
会产生如下所示的数据框:
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
对于VALUE == 1
的行,我想交换左右列的内容,以便所有“左”值最终都在“L”列下,而“右”值最终在“R”列下。
已经定义了上面的idx
变量,通过使用临时变量,我可以在另外三行中轻松完成此操作:
tmp = df.loc[idx,'L']
df.loc[idx,'L'] = df.loc[idx,'R']
df.loc[idx,'R'] = tmp
然而,这对我来说似乎是非常笨拙和不雅的语法;肯定熊猫支持更简洁的东西?我注意到如果我将输入中的列顺序交换到数据框.loc
属性,那么我得到以下交换输出:
In [2]: print(df.loc[idx,['R','L']])
R L
1 left right
3 left right
5 left right
这告诉我,通过使用以下单行,我应该能够实现与上面相同的交换:
df.loc[idx,['L','R']] = df.loc[idx,['R','L']]
然而,当我实际尝试这个时,没有任何反应 - 列保持未被破坏。就好像pandas会自动识别我在赋值语句的右侧以错误的顺序放置列,并自动纠正问题。有没有办法可以在pandas赋值语句中禁用这个“列顺序autocorrection”,以便在不创建不必要的临时变量的情况下实现交换?
答案 0 :(得分:23)
可以避免列名称对齐的一种方法是通过.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
答案 1 :(得分:3)
这里要注意的关键是pandas尝试使用索引和列名称自动对齐行和列。因此,您需要以某种方式告诉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
答案 2 :(得分:1)
您也可以使用np.select
和df.where
即
选项1 :np.select
df[['L','R']] = pd.np.select(df['VALUE'] == 1, df[['R','L']].values, df[['L','R']].values)
选项2 :df.where
df[['L','R']] = df[['R','L']].where(df['VALUE'] == 1, df[['L','R']].values)
选项3 :df.mask
df[['L','R']] = df[['L','R']].mask( df['VALUE'] == 1, df[['R','L']].values)
输出:
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