我有一个像这样的多索引 pandas 数据框:
data = np.random.random((1800,9))
col = pd.MultiIndex.from_product([('A','B','C'),('a','b','c')])
year = range(2006,2011)
month = range(1,13)
day = range(1,31)
idx = pd.MultiIndex.from_product([year,month,day], names=['Year','Month','Day'])
df1 = pd.DataFrame(data, idx, col)
其中有多索引行 Year
, Month
, Day
。我希望能够从此数据帧中选择行,就好像它是具有 DatetimeIndex 的数据帧一样。
具有 DatetimeIndex 的等效 DataFrame 为:
idx = pd.DatetimeIndex(start='2006-01-01', end='2010-12-31', freq='d')
timeidx = [ix for ix in idx if ix.day < 29]
df2 = pd.DataFrame(data, timeidx, col)
我想要的是这样的:
all(df2.ix['2006-06-06':'2008-10-11'] == df1'insert expression here')
等于 True
我知道我可以通过 df1.xs('2006', level='Year')
选择横截面,但我基本上需要一种简单的方法来复制 df2
所做的事情因为我被迫使用此索引而不是 DatetimeIndex。
最佳答案
将它们存储为字符串会立即遇到的一个问题是 '2' > '10'
,这几乎肯定不是您想要的,因此我建议使用整数。即:
year = range(2006,2011)
month = range(1,13)
day = range(1,31)
我认为你应该能够在这里使用 pd.IndexSlice,我的第一个想法是按如下方式使用它:
In [11]: idx = pd.IndexSlice
In [12]: df1.loc[idx[2006:2008, 6:10, 6:11], :]
...
但是这显示的是 2006 年 8 月至 6 月至 10 月以及 6 日至 11 日之间的数据(即 3*5*6 = 90 天)。
<小时/>所以这是一种非向量化的方式,只需比较元组:
In [21]: df1.index.map(lambda x: (2006, 6, 6) < x < (2008, 10, 11))
Out[21]: array([False, False, False, ..., False, False, False], dtype=bool)
In [22]: df1[df1.index.map(lambda x: (2006, 6, 6) < x < (2008, 10, 11))]
# just the (844) rows you want
<小时/>
如果这慢得难以忍受,一个技巧(矢量化)将是使用一些浮点表示,例如:
In [31]: df1.index.get_level_values(0).values + df1.index.get_level_values(1).values * 1e-3 + df1.index.get_level_values(2).values * 1e-6
Out[31]:
array([ 2006.001001, 2006.001002, 2006.001003, ..., 2010.012028,
2010.012029, 2010.01203 ])
关于python - 使用 pandas dataframe 根据不同级别的键范围从多索引行中进行切片的便捷方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25677929/