按列表选择列(并且列是列表的子集)

Posted

技术标签:

【中文标题】按列表选择列(并且列是列表的子集)【英文标题】:Selecting columns by list (and columns are subset of list) 【发布时间】:2017-03-30 21:50:29 【问题描述】:

我通过列名列表选择数据框的几列。如果列表的所有元素都在数据框中,这可以正常工作。 但是如果列表的某些元素不在DataFrame中,那么就会产生“not in index”的错误。

有没有办法选择该列表中包含的所有列,即使不是列表的所有元素都包含在数据框中?以下是一些产生上述错误的示例数据:

df   = pd.DataFrame( [[0,1,2]], columns=list('ABC') )

lst  = list('ARB')

data = df[lst]       # error: not in index

【问题讨论】:

【参考方案1】:

我觉得你需要Index.intersection:

df = pd.DataFrame('A':[1,2,3],
                   'B':[4,5,6],
                   'C':[7,8,9],
                   'D':[1,3,5],
                   'E':[5,3,6],
                   'F':[7,4,3])

print (df)
   A  B  C  D  E  F
0  1  4  7  1  5  7
1  2  5  8  3  3  4
2  3  6  9  5  6  3

lst = ['A','R','B']

print (df.columns.intersection(lst))
Index(['A', 'B'], dtype='object')

data = df[df.columns.intersection(lst)]
print (data)
   A  B
0  1  4
1  2  5
2  3  6

numpy.intersect1d 的另一个解决方案:

data = df[np.intersect1d(df.columns, lst)]
print (data)
   A  B
0  1  4
1  2  5
2  3  6

【讨论】:

【参考方案2】:

其他方法很少,列表理解要快得多

In [1357]: df[df.columns & lst]
Out[1357]:
   A  B
0  1  4
1  2  5
2  3  6

In [1358]: df[[c for c in df.columns if c in lst]]
Out[1358]:
   A  B
0  1  4
1  2  5
2  3  6

时间

In [1360]: %timeit [c for c in df.columns if c in lst]
100000 loops, best of 3: 2.54 µs per loop

In [1359]: %timeit df.columns & lst
1000 loops, best of 3: 231 µs per loop

In [1362]: %timeit df.columns.intersection(lst)
1000 loops, best of 3: 236 µs per loop

In [1363]: %timeit np.intersect1d(df.columns, lst)
10000 loops, best of 3: 26.6 µs per loop

详情

In [1365]: df
Out[1365]:
   A  B  C  D  E  F
0  1  4  7  1  5  7
1  2  5  8  3  3  4
2  3  6  9  5  6  3

In [1366]: lst
Out[1366]: ['A', 'R', 'B']

【讨论】:

【参考方案3】:

这里一个非常简单的解决方案是使用filter()。在您的示例中,只需键入:

df.filter(lst)

它会自动忽略任何缺失的列。有关更多信息,请参阅documentation for filter。

作为一般说明,filter 是一种选择特定列的非常灵活且强大的方法。特别是,您可以使用正则表达式。从@jezrael 借用示例数据,您可以键入以下任一内容。

df.filter(regex='A|R|B')
df.filter(regex='[ARB]')

这些只是简单的示例,但假设您只想要以这些字母开头的列,那么您可以键入:

df.filter(regex='^[ARB]')

FWIW,在某些快速的时间里,我发现这比列表理解方法要快,但我认为这里的速度并不是一个真正值得关注的问题——即使是最慢的方式也应该足够快,就像速度一样不依赖于数据框的大小,只依赖于列数。

老实说,所有这些方式都很好,您可以选择最易读的方式。我更喜欢过滤器,因为它很简单,同时还为您提供了比简单交集更多的选择列的选项。

【讨论】:

【参考方案4】:

在列表中使用*

data = df[[*lst]]

它会给出想要的结果。

【讨论】:

当我使用 Jezrael 的样本数据进行尝试时,这不起作用。老实说,我不清楚它为什么会起作用或在什么条件下会起作用......如果它起作用,你能在这里举个例子吗?顺便说一句,我没有投反对票,但如果它实际上不起作用,它可能应该被投反对票(但希望你能修复或澄清) 感谢这个非常有帮助,并且可以节省大量循环。【参考方案5】:

请试试这个:

语法:数据框[[列列表]]

例如:df[['a','b']]

a

Out[5]: 
    a  b   c
0   1  2   3
1  12  3  44

X 是要切片的 req 列列表

x = ['a','b']

这会给你 req 切片:

a[x]

Out[7]: 
    a  b
0   1  2
1  12  3

性能:

%timeit a[x]
333 µs ± 9.27 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

【讨论】:

以上是关于按列表选择列(并且列是列表的子集)的主要内容,如果未能解决你的问题,请参考以下文章

SQL 实例

从表 A 中选择与表 B 中的两列匹配的记录子集

R子集嵌套列表,选择多个条目

如何按名称选择列的子集来计算 R 中的行均值? [复制]

给出两个端点列表选择整数子集

python,计算数据框中列表的唯一列表值