【发布时间】:2015-08-28 18:43:21
【问题描述】:
我在 python pandas 中有一个数据框。数据框的结构如下:
a b c d1 d2 d3
10 14 12 44 45 78
我想选择以 d 开头的列。有没有一种简单的方法可以在 python 中实现这一点。
【问题讨论】:
标签: python python-2.7 pandas
我在 python pandas 中有一个数据框。数据框的结构如下:
a b c d1 d2 d3
10 14 12 44 45 78
我想选择以 d 开头的列。有没有一种简单的方法可以在 python 中实现这一点。
【问题讨论】:
标签: python python-2.7 pandas
您可以使用列表推导来遍历 DataFrame df 中的所有列名,然后只选择以“d”开头的那些。
df = pd.DataFrame({'a': {0: 10}, 'b': {0: 14}, 'c': {0: 12},
'd1': {0: 44}, 'd2': {0: 45}, 'd3': {0: 78}})
使用列表推导遍历数据框中的列并返回它们的名称(下面的c 是表示列名称的局部变量)。
>>> [c for c in df]
['a', 'b', 'c', 'd1', 'd2', 'd3']
然后只选择那些以'd'开头的。
>>> [c for c in df if c[0] == 'd'] # As an alternative to c[0], use c.startswith(...)
['d1', 'd2', 'd3']
最后,将此列列表传递给 DataFrame。
df[[c for c in df if c.startswith('d')]]
>>> df
d1 d2 d3
0 44 45 78
================================================ ==============================
时间(2018 年 2 月每 cmets 来自 devinbost 声称这种方法很慢...)
首先,让我们创建一个包含 30k 列的数据框:
n = 10000
cols = ['{0}_{1}'.format(letters, number)
for number in range(n) for letters in ('d', 't', 'didi')]
df = pd.DataFrame(np.random.randn(3, n * 3), columns=cols)
>>> df.shape
(3, 30000)
>>> %timeit df[[c for c in df if c[0] == 'd']] # Simple list comprehension.
# 10 loops, best of 3: 16.4 ms per loop
>>> %timeit df[[c for c in df if c.startswith('d')]] # More 'pythonic'?
# 10 loops, best of 3: 29.2 ms per loop
>>> %timeit df.select(lambda col: col.startswith('d'), axis=1) # Solution of gbrener.
# 10 loops, best of 3: 21.4 ms per loop
>>> %timeit df.filter(regex=("d.*")) # Accepted solution.
# 10 loops, best of 3: 40 ms per loop
【讨论】:
c.startswith('d') 可能更 Pythonic。不管怎样,我喜欢这个!
你可以这样使用DataFrame.filter:
import pandas as pd
df = pd.DataFrame(np.array([[2,4,4],[4,3,3],[5,9,1]]),columns=['d','t','didi'])
>>
d t didi
0 2 4 4
1 4 3 3
2 5 9 1
df.filter(regex=("d.*"))
>>
d didi
0 2 4
1 4 3
2 5 1
想法是通过regex选择列
【讨论】:
使用select:
import pandas as pd
df = pd.DataFrame([[10, 14, 12, 44, 45, 78]], columns=['a', 'b', 'c', 'd1', 'd2', 'd3'])
df.select(lambda col: col.startswith('d'), axis=1)
结果:
d1 d2 d3
0 44 45 78
如果您对正则表达式不满意,这是一个很好的解决方案。
【讨论】:
你也可以使用
df.filter(regex='^d')
【讨论】:
d结尾的列?
尤其是在更大的数据集上,矢量化方法实际上要快得多(超过两个数量级)并且可读性要好得多。 我提供截图作为证据。 (注意:除了我在底部写的最后几行以矢量化方法阐明我的观点外,其他代码来自@Alexander 的答案。)
这是供参考的代码:
import pandas as pd
import numpy as np
n = 10000
cols = ['{0}_{1}'.format(letters, number)
for number in range(n) for letters in ('d', 't', 'didi')]
df = pd.DataFrame(np.random.randn(30000, n * 3), columns=cols)
%timeit df[[c for c in df if c[0] == 'd']]
%timeit df[[c for c in df if c.startswith('d')]]
%timeit df.select(lambda col: col.startswith('d'), axis=1)
%timeit df.filter(regex=("d.*"))
%timeit df.filter(like='d')
%timeit df.filter(like='d', axis=1)
%timeit df.filter(regex=("d.*"), axis=1)
%timeit df.columns.map(lambda x: x.startswith("d"))
columnVals = df.columns.map(lambda x: x.startswith("d"))
%timeit df.filter(columnVals, axis=1)
【讨论】:
您可以使用startswith 方法与索引(本例中为列):
df.loc[:, df.columns.str.startswith('d')]
或match 使用正则表达式:
df.loc[:, df.columns.str.match('^d')]
【讨论】:
获取以 [abc] 开头直到 '_' 的列名的任何子字符串,删除所有不匹配项 (NA),删除重复项并排序。
df.columns.str.extract(r'([abc].*_)', expand=False).dropna().drop_duplicates().sort_values()
【讨论】: