在 Pandas 中对行和列 MultiIndex 使用布尔索引

2024-02-26

问题在最后,在bold。但首先,让我们设置一些数据:

import numpy as np
import pandas as pd
from itertools import product

np.random.seed(1)

team_names = ['Yankees', 'Mets', 'Dodgers']
jersey_numbers = [35, 71, 84]
game_numbers = [1, 2]
observer_names = ['Bill', 'John', 'Ralph']
observation_types = ['Speed', 'Strength']

row_indices = list(product(team_names, jersey_numbers, game_numbers, observer_names, observation_types))
observation_values = np.random.randn(len(row_indices))

tns, jns, gns, ons, ots = zip(*row_indices)

data = pd.DataFrame({'team': tns, 'jersey': jns, 'game': gns, 'observer': ons, 'obstype': ots, 'value': observation_values})

data = data.set_index(['team', 'jersey', 'game', 'observer', 'obstype'])
data = data.unstack(['observer', 'obstype'])
data.columns = data.columns.droplevel(0)

this gives: data

我想提取这个 DataFrame 的子集以供后续分析。假设我想切掉其中的行jersey号码是 71。我不太喜欢使用这个想法xs去做这个。当你通过做横截面时xs您将丢失所选的列。如果我运行:

data.xs(71, axis=0, level='jersey')

然后我找回正确的行,但我失去了jersey column.

Also, xs对于我想要一些不同值的情况,这似乎不是一个很好的解决方案jersey柱子。我认为找到了一个更好的解决方案here https://stackoverflow.com/questions/11941492/selecting-rows-from-a-pandas-dataframe-with-a-compound-hierarchical-index#comment15917600_11942697:

data[[j in [71, 84] for t, j, g in data.index]]

您甚至可以过滤球衣和球队的组合:

data[[j in [71, 84] and t in ['Dodgers', 'Mets'] for t, j, g in data.index]]

Nice!

所以问题是:我怎样才能做类似的事情来选择列的子集。例如,假设我只想要代表 Ralph 数据的列。我怎样才能做到这一点而不使用xs?或者如果我只想要包含以下内容的列怎么办observer in ['John', 'Ralph']?再说一次,我真的更喜欢一个在结果中保留行和列索引的所有级别的解决方案......就像上面的布尔索引示例一样。

我可以做我想做的事,甚至可以组合行索引和列索引中的选择。但我发现的唯一解决方案涉及一些真正的体操:

data[[j in [71, 84] and t in ['Dodgers', 'Mets'] for t, j, g in data.index]]\
    .T[[obs in ['John', 'Ralph'] for obs, obstype in data.columns]].T

因此第二个问题是:有没有更紧凑的方法来完成我上面所做的事情?


从 Pandas 0.18(可能更早)开始,您可以使用以下命令轻松地对多索引 DataFrame 进行切片pd.IndexSlice https://pandas.pydata.org/pandas-docs/stable/generated/pandas.IndexSlice.html.

对于您的具体问题,您可以使用以下内容按球队、球衣和比赛进行选择:

data.loc[pd.IndexSlice[:,[71, 84],:],:] #IndexSlice on the rows

IndexSlice 需要足够的级别信息才能明确,这样您就可以删除尾随的冒号:

data.loc[pd.IndexSlice[:,[71, 84]],:]

同样,您可以对列进行 IndexSlice:

data.loc[pd.IndexSlice[:,[71, 84]],pd.IndexSlice[['John', 'Ralph']]]

这为您提供了问题中的最终数据框。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Pandas 中对行和列 MultiIndex 使用布尔索引 的相关文章

随机推荐