从pandas DataFrame列标题获取列表


1013

我想从pandas DataFrame获取列标题的列表。DataFrame来自用户输入,所以我不知道会有多少列或它们将被称为什么。

例如,如果给我这样的数据框:

>>> my_dataframe
    y  gdp  cap
0   1    2    5
1   2    3    9
2   8    7    2
3   3    4    7
4   6    7    7
5   4    8    3
6   8    2    8
7   9    9   10
8   6    6    4
9  10   10    7

我想要一个这样的列表:

>>> header_list
['y', 'gdp', 'cap']

Answers:


1643

您可以通过执行以下操作以列表形式获取值:

list(my_dataframe.columns.values)

您也可以简单地使用:(如Ed Chum的答案所示):

list(my_dataframe)

42
为什么此文档没有columns属性?
Tjorriemorrie 2014年

@Tjorriemorrie:我不确定,这可能与他们自动生成文档的方式有关。但是在其他地方也提到过它:pandas.pydata.org/pandas-docs/stable/…–
Simeon Visser

8
我本来希望这样的df.column_names()。这个答案是正确的还是过时的?
alvas '16

1
@alvas有多种其他方法可以做到这一点(请参阅此页面上的其他答案),但据我所知,数据框上没有直接产生列表的方法。
Simeon Visser

19
重要的是,这保留了列顺序。
WindChimes

402

有一个内置的方法是最有效的:

my_dataframe.columns.values.tolist()

.columns返回一个索引,.columns.values返回一个数组,并且它具有一个帮助函数.tolist来返回列表。

如果性能对您不那么重要,则Index对象定义一种.tolist()可以直接调用的方法:

my_dataframe.columns.tolist()

性能差异很明显:

%timeit df.columns.tolist()
16.7 µs ± 317 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%timeit df.columns.values.tolist()
1.24 µs ± 12.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

对于那些谁讨厌打字,你可以叫listdf,像这样:

list(df)

4
没有投下反对票,而是要解释:不依赖于实现细节,使用DataFrame的“公共接口”。想想df.keys之美()
萨沙戈特弗里德

3
DataFrame自第一天起,@SaschaGottfried迭代器的实现就没有改变:pandas.pydata.org/pandas-docs/stable/basics.html#iteration。从DataFrame返回的可迭代对象始终是列,因此for col in df:除非开发人员崩溃,list(df)而且这样做仍然应该是有效的方法,否则这样做的行为应始终相同。请注意,df.keys()正在调用类似dict的结构的内部实现,并返回作为列的键。莫名其妙的
降票

我指的是columns属性的实现细节。一个小时前,我读到有关Demeter的定律,该定律提倡调用者不应该依赖于内部对象模型的导航。 list(df)进行显式类型转换。显着的副作用:执行时间和内存消耗随数据帧大小的增加而增加, df.keys()这是a的dict-like性质的一部分DataFrame。值得注意的事实:df.keys()无论数据框大小如何,其执行时间都相当恒定-这是熊猫开发人员的责任之一。
Sascha Gottfried

1
@SaschaGottfried我可以将此添加到我的答案中,并感谢您看到,因为没有其他人将其包括在内
EdChum

1
我可以在给定的答案和评论中看到价值-无需更改任何内容。
Sascha Gottfried

89

做了一些快速测试,使用内置版本dataframe.columns.values.tolist()最快的也许并不奇怪:

In [1]: %timeit [column for column in df]
1000 loops, best of 3: 81.6 µs per loop

In [2]: %timeit df.columns.values.tolist()
10000 loops, best of 3: 16.1 µs per loop

In [3]: %timeit list(df)
10000 loops, best of 3: 44.9 µs per loop

In [4]: % timeit list(df.columns.values)
10000 loops, best of 3: 38.4 µs per loop

list(dataframe)尽管我还是很喜欢,所以谢谢EdChum!)


47

它变得更加简单(通过pandas 0.16.0):

df.columns.tolist()

将在一个不错的列表中为您提供列名。


37
>>> list(my_dataframe)
['y', 'gdp', 'cap']

要在调试器模式下列出数据帧的列,请使用列表推导:

>>> [c for c in my_dataframe]
['y', 'gdp', 'cap']

顺便说一句,您可以使用sorted以下命令简单地得到一个排序列表:

>>> sorted(my_dataframe)
['cap', 'gdp', 'y']

list(df)仅适用于自动增量数据帧吗?还是对所有数据框都适用?
alvas

2
应该为所有人工作。但是,在调试器中时,您需要使用列表推导[c for c in df]
亚历山大

25

很奇怪,到目前为止我还没有看到这个帖子,所以我就把它留在这里。

扩展的可迭代解压缩(python3.5 +):[*df]和Friends

Python 3.5引入了拆包概述(PEP 448)。因此,以下操作都是可能的。

df = pd.DataFrame('x', columns=['A', 'B', 'C'], index=range(5))
df

   A  B  C
0  x  x  x
1  x  x  x
2  x  x  x
3  x  x  x
4  x  x  x 

如果你想要一个list....

[*df]
# ['A', 'B', 'C']

或者,如果您想要一个set

{*df}
# {'A', 'B', 'C'}

或者,如果您想要一个tuple

*df,  # Please note the trailing comma
# ('A', 'B', 'C')

或者,如果您要将结果存储在某处,

*cols, = df  # A wild comma appears, again
cols
# ['A', 'B', 'C']

...如果您是那种将咖啡转换成打字声音的人,那么,这将更有效地消耗您的咖啡;)

PS:如果性能很重要,那么您最好放弃上述解决方案,而选择

df.columns.to_numpy().tolist()
# ['A', 'B', 'C']

这与Ed Chum的答案类似,但针对v0.24进行了更新,而v0.24 .to_numpy()则首选使用.values。有关更多信息,请参阅 此答案(我本人)。

视觉检查
由于我已经在其他答案中看到了这一点,因此可以使用可迭代的拆包(无需显式循环)。

print(*df)
A B C

print(*df, sep='\n')
A
B
C

批判其他方法

不要for对可以在一行中完成的操作使用显式循环(列表理解是可以的)。

接下来,using sorted(df) 不会保留的原始顺序。为此,您应该list(df)改用。

接下来,list(df.columns)list(df.columns.values)差的建议(为当前版本,v0.24)。两者Index(从返回df.columns)和NumPy的阵列(由返回df.columns.values)限定.tolist()方法,该方法是更快和更惯用。

最后,列表化,即,list(df)仅应作为上述python <= 3.4方法的简明替代方法,其中python <= 3.4无法扩展扩展。



18

这很有趣,但是df.columns.values.tolist()快了将近三倍,df.columns.tolist()但我认为它们是相同的:

In [97]: %timeit df.columns.values.tolist()
100000 loops, best of 3: 2.97 µs per loop

In [98]: %timeit df.columns.tolist()
10000 loops, best of 3: 9.67 µs per loop

2
这个答案已经涵盖了时间。出现差异的原因是因为.values返回底层的numpy数组,并且使用numpy进行操作几乎总是比直接使用pandas进行处理更快。
cs95

17

一个数据帧遵循类似字典的遍历对象的“钥匙”的约定。

my_dataframe.keys()

创建键/列的列表-对象方法to_list()和pythonic方式

my_dataframe.keys().to_list()
list(my_dataframe.keys())

DataFrame的基本迭代返回列标签

[column for column in my_dataframe]

不要仅仅为了获取列标签而将DataFrame转换为列表。寻找方便的代码示例时,请不要停止思考。

xlarge = pd.DataFrame(np.arange(100000000).reshape(10000,10000))
list(xlarge) #compute time and memory consumption depend on dataframe size - O(N)
list(xlarge.keys()) #constant time operation - O(1)

2
我的测试表明,df.columns速度比快得多df.keys()。不确定为什么它们同时具有相同的功能和属性(嗯,这不是我第一次看到10种不同的方法来对熊猫做某事)。
cs95

1
我的回答是要展示几种从DataFrame查询列标签并突出显示性能反模式的方法。尽管如此,我还是喜欢您的意见并赞成您最近的回答-因为它们从软件工程的角度提供了价值。
Sascha Gottfried

14

在笔记本中

对于在IPython笔记本中进行数据探索,我的首选方式是:

sorted(df)

这将产生一个易于阅读的字母顺序列表。

在代码库中

在代码中,我发现这样做更加明确

df.columns

因为它告诉其他人阅读您的代码,您在做什么。


sorted(df)更改订单。请谨慎使用。
cs95

@coldspeed我确实提到了这一点,尽管“这将产生一个易于阅读的按字母顺序排列的列表”。
firelynx

9
%%timeit
final_df.columns.values.tolist()
948 ns ± 19.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%%timeit
list(final_df.columns)
14.2 µs ± 79.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit
list(final_df.columns.values)
1.88 µs ± 11.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%%timeit
final_df.columns.tolist()
12.3 µs ± 27.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%%timeit
list(final_df.head(1).columns)
163 µs ± 20.6 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

3

正如Simeon Visser回答的那样...您可以

list(my_dataframe.columns.values) 

要么

list(my_dataframe) # for less typing.

但是我认为最甜蜜的地方是:

list(my_dataframe.columns)

很明显,与此同时不必太长。


“这很明显,同时又没有必要太长。” 我不同意。list除非df直接调用(例如,简洁),否则调用没有任何优点。访问该.columns属性将返回一个Index对象,该对象上具有tolist()定义的方法,并且调用该对象比列出该对象更惯用Index。仅出于完整性考虑而混合使用成语并不是一个好主意。列出从中得到的数组也一样.values
cs95,19年

3

为了进行快速,整洁的外观检查,请尝试以下操作:

for col in df.columns:
    print col

3

这为我们提供了列表中列的名称:

list(my_dataframe.columns)

也可以使用另一个称为tolist()的函数:

my_dataframe.columns.tolist()

其他答案已经涵盖了这一点。您的第一个解决方案还混合了成语,这不是一个好主意。看到我的评论下另一个答案。
cs95,19年

2

我觉得问题值得进一步解释。

正如@fixxxer指出的,答案取决于您在项目中使用的熊猫版本。您可以通过pd.__version__命令获得。

如果您出于某种原因(在我的Debian jessie上使用0.14.1)使用了比0.16.0更旧的熊猫,那么您需要使用:

df.keys().tolist()因为还没有df.columns实现任何方法。

这种密钥方法的优点是,即使在较新版本的熊猫中也可以使用,因此更加通用。


keys()的缺点是它是一个函数调用而不是属性查找,因此它总是很慢。当然,在访问时间恒定的情况下,没有人真正在乎这样的差异,但是我认为还是值得一提。df.columns现在是访问标头的更普遍接受的习惯用法。
cs95


0

即使上面提供的解决方案很好。我也希望像frame.column_names()这样的东西在熊猫中是一个函数,但是由于不是,所以使用以下语法可能会很好。通过调用“ tolist”函数,它以某种方式保留了您以正确方式使用熊猫的感觉:frame.columns.tolist()

frame.columns.tolist() 

0

如果DataFrame恰好有一个Index或MultiIndex,并且您也希望将它们作为列名包括在内:

names = list(filter(None, df.index.names + df.columns.values.tolist()))

它避免了调用reset_index(),因为这种简单的操作会对性能造成不必要的影响。

我经常遇到这种情况,因为我正在从数据帧索引映射到主键/唯一键的数据库中穿梭数据,但实际上这只是我的另一个“列”。对于大熊猫来说,为这样的事情提供内置方法可能是有道理的(我完全可能错过了它)。


-1

此解决方案列出了对象my_dataframe的所有列:

print(list(my_dataframe))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.