python中multiindex如何索引_关于python:如何使用另一个MultiIndex对一个MultiIndex DataFrame进行切片...

本文介绍如何在Python的pandas库中使用MultiIndex对DataFrame进行高效索引。通过示例展示了如何创建一个3级MultiIndex DataFrame,然后利用IndexSlice、.loc、.isin()方法以及布尔索引来切片数据。同时提到了使用query()方法来表达更复杂的查询条件,以及当切片条件来自于另一个DataFrame的索引时如何操作。
摘要由CSDN通过智能技术生成

我有一个包含3个MultiIndex级别的pandas数据帧。 我试图根据对应于两个级别的值列表拉出此数据帧的行。

我有这样的事情:

ix = pd.MultiIndex.from_product([[1, 2, 3], ['foo', 'bar'], ['baz', 'can']], names=['a', 'b', 'c'])

data = np.arange(len(ix))

df = pd.DataFrame(data, index=ix, columns=['hi'])

print(df)

hi

a b   c

1 foo baz   0

can   1

bar baz   2

can   3

2 foo baz   4

can   5

bar baz   6

can   7

3 foo baz   8

can   9

bar baz  10

can  11

现在我想要获取索引级别'b'和'c'在此索引中的所有行:

ix_use = pd.MultiIndex.from_tuples([('foo', 'can'), ('bar', 'baz')], names=['b', 'c'])

即,hi的值hi或('bar', 'baz')分别为b和c:(1, 2, 5, 6, 9, 10)。

所以我想在第一级采用slice(None),并在第二级和第三级取出特定的元组。

最初我认为将多索引对象传递给.loc会拉出我想要的值/级别,但这不起作用。 做这样的事情最好的方法是什么?

我有几个不同的尝试让这个工作。 我想我找到了一个不错的解决方法,这个目前似乎有点困难。 试试看!

以下是获取此切片的方法:

df.sort_index(inplace=True)

idx = pd.IndexSlice

df.loc[idx[:, ('foo','bar'), 'can'], :]

生产

hi

a b   c

1 bar can   3

foo can   1

2 bar can   7

foo can   5

3 bar can  11

foo can   9

请注意,您可能需要先对MultiIndex进行排序,然后才能对其进行切片。如果你需要这么做,熊猫就足够警告了:

KeyError: 'MultiIndex Slicing requires the index to be fully lexsorted tuple len (3), lexsort depth (1)'

您可以在文档中阅读有关如何使用切片器的更多信息

如果由于某种原因使用切片器不是一个选项,这是一种使用.isin()方法获得相同切片的方法:

df[df.index.get_level_values('b').isin(ix_use.get_level_values(0)) & df.index.get_level_values('c').isin(ix_use.get_level_values(1))]

这显然不那么简洁。

更新:

对于您在此处更新的条件是一种方法:

cond1 = (df.index.get_level_values('b').isin(['foo'])) & (df.index.get_level_values('c').isin(['can']))

cond2 = (df.index.get_level_values('b').isin(['bar'])) & (df.index.get_level_values('c').isin(['baz']))

df[cond1 | cond2]

生产:

hi

a b   c

1 foo can   1

bar baz   2

2 foo can   5

bar baz   6

3 foo can   9

bar baz  10

这非常接近我正在寻找的东西,但我应该更清楚地表达这个问题。 实际上,我需要的是来自级别"c"的值,它取决于级别"b"中的值。 例如,任何时候级别"b"是'foo',我想要级别"c"是'can'的值,并且任何时候级别"b"是'bar',我想要级别"c"的值 是'巴兹'

用这两个条件更新了答案,这应该让我们知道如何处理这个问题。

我会推荐query()方法,就像在这个Q& A中一样。

简单地使用这个,我认为这是一种更自然的表达方式:

In [27]: df.query("(b == 'foo' and c == 'can') or (b == 'bar' and c == 'baz')")

Out[27]:

hi

a b   c

1 foo can   1

bar baz   2

2 foo can   5

bar baz   6

3 foo can   9

bar baz  10

我觉得有趣的是这不起作用:

In [45]: df.loc[(idx[:, 'foo', 'can'], idx[:, 'bar', 'baz']), ]

Out[45]:

hi

a b   c

1 bar baz   2

can   3

foo baz   0

can   1

2 bar baz   6

can   7

foo baz   4

can   5

3 bar baz  10

can  11

foo baz   8

can   9

不知何故,它看起来像"应该"。无论如何,这是一个合理的解决方法:

让我们假设您想要切片的元组位于另一个DataFrame的索引中(因为听起来它们可能就在您的情况下!)。

In [53]: ix_use = pd.MultiIndex.from_tuples([('foo', 'can'), ('bar', 'baz')], names=['b', 'c'])

In [55]: other = pd.DataFrame(dict(a=1), index=ix_use)

In [56]: other

Out[56]:

a

b   c

foo can  1

bar baz  1

现在要按other的索引切片df,我们可以使用.loc / .ix允许你给出元组列表的事实(参见这里的最后一个例子)。

首先让我们构建我们想要的元组列表:

In [13]: idx = [(x, ) + y for x in df.index.levels[0] for y in other.index.values]

In [14]: idx

Out[14]:

[(1, 'foo', 'can'),

(1, 'bar', 'baz'),

(2, 'foo', 'can'),

(2, 'bar', 'baz'),

(3, 'foo', 'can'),

(3, 'bar', 'baz')]

现在我们可以将此列表传递给.ix或.loc:

In [17]: df.ix[idx]

Out[17]:

hi

a b   c

1 foo can   1

bar baz   2

2 foo can   5

bar baz   6

3 foo can   9

bar baz  10

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值