首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用一行交换pandas数据框中所选行的列值,正确的语法是什么?

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

Stack Overflow用户
提问于 2014-09-12 00:28:32
回答 3查看 22.4K关注 0票数 29

我使用的是pandas版本0.14.1和Python2.7.5,并且我有一个包含三列的数据帧,例如:

代码语言:javascript
复制
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)

生成如下所示的数据框:

代码语言:javascript
复制
       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变量之后,我可以很容易地在另外三行代码中完成这项工作,只需使用一个临时变量,如下所示:

代码语言:javascript
复制
tmp = df.loc[idx,'L']
df.loc[idx,'L'] = df.loc[idx,'R']
df.loc[idx,'R'] = tmp

然而,在我看来,这似乎真的很笨拙和不优雅的语法;难道熊猫支持更简洁的语法吗?我注意到,如果将输入中的列顺序交换为数据框.loc属性,则会得到以下交换后的输出:

代码语言:javascript
复制
In [2]: print(df.loc[idx,['R','L']])
      R      L
1  left  right
3  left  right
5  left  right

这向我表明,我应该能够实现与上面相同的交换,只需使用以下一行:

代码语言:javascript
复制
df.loc[idx,['L','R']] = df.loc[idx,['R','L']]

但是,当我实际尝试这样做时,什么也没有发生--列保持不交换。这就好像pandas自动意识到我在赋值语句的右侧以错误的顺序放置了列,它会自动纠正这个问题。有没有一种方法可以在pandas赋值语句中禁用这个“列顺序自动更正”,以便在不创建不必要的临时变量的情况下实现交换?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-09-12 00:40:47

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

代码语言:javascript
复制
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
票数 33
EN

Stack Overflow用户

发布于 2014-09-12 01:34:25

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

代码语言:javascript
复制
>>> 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
票数 8
EN

Stack Overflow用户

发布于 2017-12-31 11:15:47

您也可以使用np.select和df.where来实现这一点

选项1:np.select

代码语言:javascript
复制
df[['L','R']] = pd.np.select(df['VALUE'] == 1, df[['R','L']].values, df[['L','R']].values)

选项2:df.where

代码语言:javascript
复制
df[['L','R']] = df[['R','L']].where(df['VALUE'] == 1, df[['L','R']].values)

选项3:df.mask

代码语言:javascript
复制
df[['L','R']] = df[['L','R']].mask( df['VALUE'] == 1, df[['R','L']].values)

输出:

代码语言:javascript
复制
    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
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25792619

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档