在 Pandas 数据帧中选择多个列

1723
如何从df中选择列a和b,并将它们保存到新的数据框df1中?
index  a   b   c
1      2   3   4
2      3   4   5

尝试失败:

df1 = df['a':'b']
df1 = df.ix[:, 'a':'b']
24个回答

2652

您尝试的方式无法切片列名(即字符串)。

这里有几个选择。 如果您知道要从上下文中切片哪些变量,则可以通过将列表传递到 __getitem__ 语法(方括号)中,仅返回这些列的视图。

df1 = df[['a', 'b']]

另外,如果对它们进行编号而不是按名称排序很重要(比如说你的代码需要自动完成这个任务,但不知道前两列的名称),那么你可以使用以下方法:

df1 = df.iloc[:, 0:2] # Remember that Python does not slice inclusive of the ending index.

另外,您应该熟悉 Pandas 对象的视图和副本的概念。上述方法中的第一个方法将返回所需子对象(所需切片)的内存中的新副本。

然而,有时 Pandas 中的索引约定不会这样做,而是给您一个新变量,该变量只是指向原始对象中的子对象或切片的相同内存块。这将在第二种索引方式下发生,因此您可以使用 .copy() 方法来修改它以获取常规副本。当发生这种情况时,更改您认为是切片对象的内容有时会更改原始对象的内容。时刻警惕这种情况的发生。

df1 = df.iloc[0, 0:2].copy() # To avoid the case where changing df1 also changes df

要使用iloc,您需要知道列的位置(或索引)。由于列位置可能会发生变化,因此您可以使用数据帧对象的columns方法中的get_loc函数与iloc一起获取列索引,而不是硬编码索引。

{df.columns.get_loc(c): c for idx, c in enumerate(df.columns)}

现在你可以使用这个字典通过名称和 iloc 访问列。


294
注意: df[['a','b']] 会产生一个副本。 - Wes McKinney

277

从0.11.0版本开始,可以使用.loc索引器对列进行切片操作:

df.loc[:, 'C':'E']

等同于

df[['C', 'D', 'E']]  # or df.loc[:, ['C', 'D', 'E']]

并返回列CE


在一个随机生成的DataFrame上演示:

import pandas as pd
import numpy as np
np.random.seed(5)
df = pd.DataFrame(np.random.randint(100, size=(100, 6)),
                  columns=list('ABCDEF'),
                  index=['R{}'.format(i) for i in range(100)])
df.head()

Out:
     A   B   C   D   E   F
R0  99  78  61  16  73   8
R1  62  27  30  80   7  76
R2  15  53  80  27  44  77
R3  75  65  47  30  84  86
R4  18   9  41  62   1  82

要获取从CE的列(注意,与整数切片不同,E包含在列中):

df.loc[:, 'C':'E']

Out:
      C   D   E
R0   61  16  73
R1   30  80   7
R2   80  27  44
R3   47  30  84
R4   41  62   1
R5    5  58   0
...

对于基于标签选择行的操作也是如此。从那些列中获取 R6R10 行:

df.loc['R6':'R10', 'C':'E']

Out:
      C   D   E
R6   51  27  31
R7   83  19  18
R8   11  67  65
R9   78  27  29
R10   7  16  94

.loc 同样可以接受一个布尔数组,因此您可以选择与数组中对应条目为 True 的列。例如,df.columns.isin(list('BCD')) 返回 array([False, True, True, True, False, False], dtype=bool) - 如果列名在列表 ['B', 'C', 'D'] 中,则为True;否则为False。

df.loc[:, df.columns.isin(list('BCD'))]

Out:
      B   C   D
R0   78  61  16
R1   27  30  80
R2   53  80  27
R3   65  47  30
R4    9  41  62
R5   78   5  58
...

142
假设您的列名(df.columns)是['index','a','b','c'] ,则您想要的数据位于第三和第四列。如果脚本运行时不知道它们的名称,您可以这样做。
newdf = df[df.columns[2:4]] # Remember, Python is zero-offset! The "third" entry is at slot two.

正如EMS在他的回答中所指出的那样,df.ix可以更简洁地选择列,但是.columns切片接口可能更自然,因为它使用标准的一维Python列表索引/切片语法。

警告'index'是一个DataFrame列的不好的名称。同样的标签也用于真实的df.index属性,即一个Index数组。因此,您的列可以通过df['index']返回,而真实的DataFrame索引可以通过df.index返回。Index是一种特殊类型的Series,它针对其元素值的查找进行了优化。对于df.index,它用于根据其标签查找行。该df.columns属性也是一个pd.Index数组,用于按其标签查找列。


96
在最新版本的Pandas中,有一种简单的方法可以做到这一点。列名称(字符串)可以以任何你喜欢的方式进行切片。
columns = ['b', 'c']
df1 = pd.DataFrame(df, columns=columns)

79
In [39]: df
Out[39]: 
   index  a  b  c
0      1  2  3  4
1      2  3  4  5

In [40]: df1 = df[['b', 'c']]

In [41]: df1
Out[41]: 
   b  c
0  3  4
1  4  5

需要解释一下。例如,要点是什么?您可以编辑您的答案 - 不要包含“编辑:”、“更新:”或类似内容 - 答案应该看起来像是今天写的。 - Peter Mortensen

54

使用Pandas,

使用列名

dataframe[['column1','column2']]

使用iloc和指定的列索引进行选择:

dataframe.iloc[:,[1,2]]

带有 loc 列名的数据可以像这样使用


dataframe.loc[:,['column1','column2']]

38
您可以使用方法来过滤或重新排序列,如下所示:

df1 = df.filter(['a', 'b'])

当您需要链接多个方法时,这也非常有用。


29
您可以提供要删除的列列表,并使用Pandas DataFrame上的drop()函数仅返回所需的列的DataFrame。
顺便说一下。
colsToDrop = ['a']
df.drop(colsToDrop, axis=1)

将返回仅包含列bc的DataFrame。

drop方法的文档在此处


26

我发现这种方法非常有用:

# iloc[row slicing, column slicing]
surveys_df.iloc [0:3, 1:4]

更多详细信息请点击这里


25

从0.21.0版本开始,使用.loc[]在一个具有一个或多个缺失标签的列表中已被弃用,推荐使用.reindex。因此,你的问题的答案是:

df1 = df.reindex(columns=['b','c'])

以前的版本中,使用.loc[list-of-labels]只要其中至少有一个标签被找到就能正常工作(否则会引发KeyError)。这种行为已经被弃用,现在会显示警告信息。推荐的替代方法是使用.reindex()

阅读更多内容请访问索引和选择数据


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接