【发布时间】:2014-01-12 08:00:12
【问题描述】:
问题在最后,用粗体。但首先,让我们设置一些数据:
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)
这给出:
我想提取此 DataFrame 的一个子集以供后续分析。假设我想切掉 jersey 数字为 71 的行。我不太喜欢使用 xs 执行此操作的想法。当您通过xs 进行横截面时,您会丢失您选择的列。如果我跑:
data.xs(71, axis=0, level='jersey')
然后我找回正确的行,但我丢失了 jersey 列。
另外,xs 对于我想要来自jersey 列的一些不同值的情况似乎不是一个很好的解决方案。我认为一个更好的解决方案是找到here:
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]]
不错!
所以问题是:我怎样才能做类似的事情来选择列的子集。例如,假设我只想要代表来自 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
因此是第二个问题:有没有更紧凑的方法来完成我刚才所做的事情?
【问题讨论】:
-
很好的方法,但你的问题是什么?
-
@MattDMo 我已经加粗上面的具体问题。更一般地说:我想我在上面展示了一些强大但语法丑陋的食谱。我希望有一种更直接的方式来完成我在那里所做的事情。具体来说,我正在寻找一种方法,该方法将根据一个或多个行索引中的值限制行,同时根据一个或多个列索引中的值限制列。非常希望有人能提出更自然的方法。
-
有趣的问题。对于单元素过滤器情况,您可以传递
drop_level=False以避免丢失Jersey列。请注意,您可以写data.loc[[j in [71, 84] and t in ['Dodgers', 'Mets'] for t, j, g in data.index], [obs in ['John', 'Ralph'] for obs, obstype in data.columns]],而不是转置。 -
@DSM 这也是迄今为止最快的解决方案(只是),虽然 loc 在这里看起来 slow... 似乎这可能是一个很好的功能请求。
-
@AndyHayden:我不介意
df.fx(rows={"jersey": [71], "team": ["Dodgers", "Mets"]}, columns={"observer": ["John", "Ralph"]})这样的东西,它基本上可以满足这里的需求。
标签: python pandas multi-index