熊猫:切片多索引与许多索引

Posted

技术标签:

【中文标题】熊猫:切片多索引与许多索引【英文标题】:pandas: slice Multindex with many indices 【发布时间】:2019-10-28 04:38:09 【问题描述】:

我有一个数据框d,其中包含大约100,000,000 行和3 列。它看起来像这样:

import pandas as pd 

In [17]: d = pd.DataFrame('id': ['a', 'b', 'c', 'd', 'e'], 'val': [1, 2, 3, 4, 5], 'n': [34, 22, 95, 86, 44]) 

In [18]: d.set_index(['id', 'val'], inplace = True)

我有另一个数据框,其值为idval,我想保留在d 中。我想保留大约 600,000 个 idval 组合:

In [20]: keep = pd.DataFrame('id':['a', 'b'], 'val' : [1, 2])

我已经通过以下方式进行了尝试:

In [21]: keep.set_index(['id', 'val'], inplace = True)

In [22]: d.loc[d.index.isin(keep.index), :] 
Out [22]:         
                   n
         id val    
          a  1    34
          b  2    22

这可行,但看起来很笨重而且很慢。这里有更好的方法吗?在 Pandas 中对 Multindex 进行切片的最快方法是什么?

【问题讨论】:

操作!请接受WeNYoBen 的回答,因为我相信您会获得 2 倍的速度。 谢谢!请注意,MultiIndex.from_frame 是 .24 中的新内容。烦人的是,我必须在带有 pandas .23 的服务器上运行它。 那么组合应该可以工作d.reindex(list(zip(*map(keep.get, keep)))]) 完美,谢谢!这似乎比 .loc 【参考方案1】:

使用loc 索引d 使用keep

# d.loc[pd.MultiIndex.from_arrays([keep['id'], keep['val']]))]
d.reindex(pd.MultiIndex.from_arrays([keep['id'], keep['val']])))

         n
id val    
a  1    34
b  2    22

在哪里,

pd.MultiIndex.from_arrays([keep['id'], keep['val']])

MultiIndex(levels=[['a', 'b'], [1, 2]],
           codes=[[0, 1], [0, 1]],
           names=['id', 'val'])

keep 生成一个用于过滤的 MultiIndex。


另一种选择是尝试与df.merge 合并:

d.merge(keep, left_index=True, right_on=['id', 'val'])

    n id  val
0  34  a    1
1  22  b    2

d.merge(keep, left_index=True, right_on=['id', 'val']).set_index(['n', 'id'])

       val
n  id     
34 a     1
22 b     2

甚至,

d.join(keep.set_index(['id', 'val']), how='inner')

         n
id val    
a  1    34
b  2    22

【讨论】:

这很可爱d.merge(keep, on=[*keep]).set_index([*keep]) @piRSquared Nice,适用于具有这些列名称的示例:)【参考方案2】:

loc 获取用于引用MultiIndex 的元组列表

d.loc[[*keep.itertuples(index=False)]]

         n
id val    
a  1    34
b  2    22

做同样事情的更令人讨厌的方式。 (实际上不是推荐)

d.loc[[*zip(*map(keep.get, keep))]]

         n
id val    
a  1    34
b  2    22

优点是少了 3 个字符。您只需要牺牲了解正在发生的事情。

【讨论】:

我喜欢这种简洁性,但我怀疑itertuples 会解决“在 Pandas 中对 Multindex 进行切片的最快方法是什么?”。第二个应该。 谢谢 -- d.loc[[*keep.itertuples(index=False)]] 给了我一个语法错误,但 d.loc[keep.itertuples(index=False)] 有效。 @svenkatesh 这是一个 python 版本问题。使用适合您的方法 @cs95 keep.itertuples(index=False, name=False) 一样快。是命名元组的创建减慢了它的速度。【参考方案3】:

使用reindex

d.reindex(pd.MultiIndex.from_frame(keep))
Out[151]: 
         n
id val    
a  1    34
b  2    22

【讨论】:

TIL pd.MultiIndex.from_frame 这个答案比我的有两个优点:1. reindex 更快,我应该使用它而不是loc,但我想要更少的字符。 2. pd.MultiIndex.from_frame 也很快。 是的,我确实把这个问题和 TIL from_frame 搞砸了。手感不错! @WeNYoBen 这适用于我的问题的玩具示例,当我在 d 上有一个唯一的 MultiIndex 时。在我的真实数据集中,我得到以下信息:Exception: cannot handle a non-unique multi-index! 有什么建议吗? @svenkatesh 那么你可能需要使用 isin 方法,同样为了代码安全,最好不要保留重复索引。

以上是关于熊猫:切片多索引与许多索引的主要内容,如果未能解决你的问题,请参考以下文章

将熊猫多索引切片彼此分开

熊猫切片多索引数据框

切片具有大列表的多索引熊猫数据框

熊猫如何切片多索引数据框?

将值从一个数据帧切片复制到另一个:使用“IndexSlice”的多索引熊猫数据帧的切片是不是总是一致地排序?

使用部分索引元组列表对多索引数据帧进行切片的最佳方法是啥?