使用 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
我们要选择列a
和b
。
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 删除不需要的列会更方便。它可以批量删除几列。
要选择a
和b
,请删除c
和d
。
df.drop(['c', 'd'], level=1, axis=1)
【讨论】:
以上是关于使用 pandas xs 功能进行多列选择失败的主要内容,如果未能解决你的问题,请参考以下文章
Pandas列表的列,通过迭代(选择)三列的每个列表元素作为新列和行来创建多列[重复]
4、pandas的数据筛选之isin和str.contains函数