使用 pandas xs 功能进行多列选择失败

Posted

技术标签:

【中文标题】使用 pandas xs 功能进行多列选择失败【英文标题】:multi column selection with pandas xs function is failed 【发布时间】:2016-07-31 00:04:47 【问题描述】:

我有以下多索引时间序列数据。

first                001                                               \
second              open     high      low    close jdiff_vol   value   
date     time                                                           
20150721 90100   2082.18  2082.18  2082.18  2082.18     11970   99466   
         90200   2082.72  2083.01  2082.18  2083.01      4886   40108   
         90300   2083.68  2084.20  2083.68  2083.98      6966   48847   
         90400   2083.63  2084.21  2083.63  2084.00      6817   48020   
         90500   2084.03  2084.71  2083.91  2084.32     10193   58399   
20150721 90100   2084.14  2084.22  2083.59  2083.65      7860   39128   
         90200   2084.08  2084.08  2083.47  2083.50      7171   39147   
         90300   2083.25  2083.65  2083.08  2083.60      4549   34373   
         90400   2084.06  2084.06  2083.66  2083.80      6980   38088   
         90500   2083.61  2084.04  2083.27  2083.89      5292   33466   

以下代码有效。

opens = data.xs('open', level='second', axis=1, drop_level=True)

但是,使用以下代码选择多列失败。

opens = data.xs(('open','close'), level='second', axis=1, drop_level=True)

如何修改它以选择多列?

【问题讨论】:

你好像少了一个逗号opens = data.xs(('open','close'), level='second', axis=1, drop_level=True)这是一个错字吗? @EdChum 感谢您的评论。我修正了错字。 【参考方案1】:

我不能用find 解决xs

但您可以使用loc,但首先必须按sort_index 对列进行排序:

data = data.sort_index(axis=1)

print data.loc[:,(slice(None),('open','close'))]
first               001         
second            close     open
date     time                   
20150721 90100  2082.18  2082.18
         90200  2083.01  2082.72
         90300  2083.98  2083.68
         90400  2084.00  2083.63
         90500  2084.32  2084.03
         90100  2083.65  2084.14
         90200  2083.50  2084.08
         90300  2083.60  2083.25
         90400  2083.80  2084.06
         90500  2083.89  2083.61

【讨论】:

【参考方案2】:

直到现在,pandas xs() 函数还不能在同一级别使用两个列键。只能使用来自不同级别的两个键:

opens = data.xs(('001','close'), level=('first','second'), axis=1, drop_level=True)

但是,这并不是您想要的。另一种解决方案是执行两个 pandas xs() 函数并在之后concat它们:

df_xs = pd.concat([df.xs('open', level='second', axis=1, drop_level=True), df.xs('close', level='second', axis=1, drop_level=True)])

这是一个完整的例子。首先,创建一个数据框:

import pandas as pd
import numpy as np

arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
          ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df = pd.DataFrame(np.random.randn(6, 6), index=index[:6], columns=index[:6])

print(df)

first              bar                 baz                 foo          
second             one       two       one       two       one       two
first second                                                            
bar   one     0.699065 -0.283550  0.072595 -0.699627  0.879832 -1.787520
      two    -1.172970  1.381607  1.941370  0.577451 -0.182819  0.215879
baz   one     0.669402 -0.018534  0.775114  1.277079  0.404116 -2.450712
      two     0.066530 -0.509366  1.249981  2.426217  0.409881 -0.178713
foo   one     1.098217  0.399427 -1.423057 -1.261542  1.668202  0.187629
      two     0.827283  0.974239 -1.944796  0.266321  0.700679 -0.371074

然后你可以执行带有 concat 的 xs():

df_xs = pd.concat([df.xs('one', level='second', axis=1, drop_level=True), df.xs('two', level='second', axis=1, drop_level=True)])
print (df_xs)

first              bar       baz       foo
first second                              
bar   one     0.699065  0.072595  0.879832
      two    -1.172970  1.941370 -0.182819
baz   one     0.669402  0.775114  0.404116
      two     0.066530  1.249981  0.409881
foo   one     1.098217 -1.423057  1.668202
      two     0.827283 -1.944796  0.700679
bar   one    -0.283550 -0.699627 -1.787520
      two     1.381607  0.577451  0.215879
baz   one    -0.018534  1.277079 -2.450712
      two    -0.509366  2.426217 -0.178713
foo   one     0.399427 -1.261542  0.187629
      two     0.974239  0.266321 -0.371074

【讨论】:

【参考方案3】:

例子:

df = pd.DataFrame(
    [[1,2,3,4,5,6,7,8]],
    columns=pd.MultiIndex.from_product([['A','B'], ['a', 'b', 'c', 'd']])
)

Out:
A               B
a   b   c   d   a   b   c   d
1   2   3   4   5   6   7   8

我们要选择列ab

Out:
A       B
a   b   a   b
1   2   5   6

解决方案 1:正向选择(与 jezrael 的想法相同)

使用pandas.MultiIndex.get_loc搜索列的位置并选择它们

select = df.columns.get_level_values(1).isin(['a', 'b'])
df.loc[:, select]

解决方案 2:负选择

要解决这个问题,不尝试选择感兴趣的列,而是使用pandas.DataFrame.drop 删除不需要的列会更方便。它可以批量删除几列。

要选择ab,请删除cd

df.drop(['c', 'd'], level=1, axis=1)

【讨论】:

以上是关于使用 pandas xs 功能进行多列选择失败的主要内容,如果未能解决你的问题,请参考以下文章

使用 python pandas 在多个列中进行选择?

Pandas列表的列,通过迭代(选择)三列的每个列表元素作为新列和行来创建多列[重复]

14.pandas里面按条件筛选

4、pandas的数据筛选之isin和str.contains函数

有哪个文本编辑器可以像EXCE那样进行多行多列不连续选择的吗?

Pandas:按行从 DataFrame 的特定列中选择值