我有一个DataFrame"df"与(时间,股票代码)Multiindex和bid/ask/etc数据列:
tod last bid ask volume
time ticker
2013-02-01 SPY 1600 149.70 150.14 150.17 1300
SLV 1600 30.44 30.38 30.43 3892
GLD 1600 161.20 161.19 161.21 3860
我想使用多个键选择二级(level = 1)横截面.现在,我可以用一把钥匙来做,即
df.xs('SPY', level=1)
这给了我SPY的时间序列.选择多键横截面的最佳方法是什么,即SPY和GLD的组合横截面,如:
df.xs(['SPY', 'GLD'], level=1)
?
除了使用以外,我找不到更直接的方法select:
>>> df
last tod
A SPY 1 1600
SLV 2 1600
GLD 3 1600
>>> df.select(lambda x: x[1] in ['SPY','GLD'])
last tod
A SPY 1 1600
GLD 3 1600
Run Code Online (Sandbox Code Playgroud)
小智 7
使用更新版本的Pandas有更好的方法:
regression_df.loc[(slice(None), ['SPY', 'GLD']), :]
Run Code Online (Sandbox Code Playgroud)
这种方法要求索引按字典顺序排序(使用df.sort_index()).
为了它的价值,我做了以下事情:
\n\nfoo = pd.DataFrame(np.random.rand(12,3), \n index=pd.MultiIndex.from_product([['A','B','C','D'],['Green','Red','Blue']], \n names=['Letter','Color']),\n columns=['X','Y','Z']).sort_index()\n\nfoo.reset_index()\\\n .loc[foo.reset_index().Color.isin({'Green','Red'})]\\\n .set_index(foo.index.names)\nRun Code Online (Sandbox Code Playgroud)\n\n此方法类似于 select,但避免使用 lambda 迭代所有行。
\n\n不过,我将其与 Panel 方法进行了比较,发现 Panel 解决方案速度更快(index/loc 为 2.91 毫秒,to_panel/to_frame 为 1.48 毫秒:
\n\nfoo.to_panel()[:,:,['Green','Red']].to_frame()\nRun Code Online (Sandbox Code Playgroud)\n\n次数:
\n\nIn [56]:\n%%timeit\nfoo.reset_index().loc[foo.reset_index().Color.isin({'Green','Red'})].set_index(foo.index.names)\n100 loops, best of 3: 2.91 ms per loop\n\nIn [57]:\n%%timeit\nfoo2 = foo.reset_index()\nfoo2.loc[foo2.Color.eq('Green') | foo2.Color.eq('Red')].set_index(foo.index.names)\n100 loops, best of 3: 2.85 ms per loop\n\nIn [58]:\n%%timeit\nfoo2 = foo.reset_index()\nfoo2.loc[foo2.Color.ne('Blue')].set_index(foo.index.names)\n100 loops, best of 3: 2.37 ms per loop\n\nIn [54]:\n%%timeit\nfoo.to_panel()[:,:,['Green','Red']].to_frame()\n1000 loops, best of 3: 1.18 ms per loop\nRun Code Online (Sandbox Code Playgroud)\n\n更新
\n\n在(再次)重新审视这个主题后,我观察到以下内容:
\n\nIn [100]:\n%%timeit\nfoo2 = pd.DataFrame({k: foo.loc[k] for k in foo.index if k[1] in ['Green','Red']}).transpose()\nfoo2.index.names = foo.index.names\nfoo2.columns.names = foo2.columns.names\n100 loops, best of 3: 1.97 ms per loop\n\nIn [101]:\n%%timeit\nfoo2 = pd.DataFrame.from_dict({k: foo.loc[k] for k in foo.index if k[1] in ['Green','Red']}, orient='index')\nfoo2.index.names = foo.index.names\nfoo2.columns.names = foo2.columns.names\n100 loops, best of 3: 1.82 ms per loop\nRun Code Online (Sandbox Code Playgroud)\n\n如果您不关心保留级别的原始顺序和命名,您可以使用:
\n\n%%timeit\npd.concat({key: foo.xs(key, axis=0, level=1) for key in ['Green','Red']}, axis=0)\n1000 loops, best of 3: 1.31 ms per loop\nRun Code Online (Sandbox Code Playgroud)\n\n如果您只是在第一级进行选择:
\n\n%%timeit\npd.concat({key: foo.loc[key] for key in ['A','B']}, axis=0, names=foo.index.names)\n1000 loops, best of 3: 1.12 ms per loop\nRun Code Online (Sandbox Code Playgroud)\n\n相对:
\n\n%%timeit\nfoo.to_panel()[:,['A','B'],:].to_frame()\n1000 loops, best of 3: 1.16 ms per loop\nRun Code Online (Sandbox Code Playgroud)\n\n另一个更新
\n\n如果对示例的索引进行排序foo,上面的许多时间都会得到改善(时间已更新以反映预排序的索引)。不过,当索引排序时,可以使用user674155描述的解决方案:
%%timeit\nfoo.loc[(slice(None), ['Blue','Red']),:]\n1000 loops, best of 3: 582 \xc2\xb5s per loop\nRun Code Online (Sandbox Code Playgroud)\n\n在我看来,这是最有效和直观的(用户不需要了解面板以及它们是如何从框架创建的)。
\n\n注意:即使索引尚未排序,foo动态排序索引在性能上也与该to_panel选项相当。
| 归档时间: |
|
| 查看次数: |
6273 次 |
| 最近记录: |