pandas:通过二级索引范围切片 MultiIndex

2024-03-28 21:37:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个多索引的系列:

import numpy as np
import pandas as pd

buckets = np.repeat(['a','b','c'], [3,5,1])
sequence = [0,1,5,0,1,2,4,50,0]

s = pd.Series(
    np.random.randn(len(sequence)), 
    index=pd.MultiIndex.from_tuples(zip(buckets, sequence))
)

# In [6]: s
# Out[6]: 
# a  0    -1.106047
#    1     1.665214
#    5     0.279190
# b  0     0.326364
#    1     0.900439
#    2    -0.653940
#    4     0.082270
#    50   -0.255482
# c  0    -0.091730

我想得到第二个索引('sequence')在2到10之间的s['b']值。

对第一个索引进行切片可以很好地工作:

s['a':'b']
# Out[109]: 
# bucket  value
# a       0        1.828176
#         1        0.160496
#         5        0.401985
# b       0       -1.514268
#         1       -0.973915
#         2        1.285553
#         4       -0.194625
#         5       -0.144112

但在第二个问题上,至少从两个最明显的方面来看是这样的:

1)返回元素1到4,与索引值无关

s['b'][1:10]

# In [61]: s['b'][1:10]
# Out[61]: 
# 1     0.900439
# 2    -0.653940
# 4     0.082270
# 50   -0.255482

但是,如果我反转索引,并且第一个索引是整数,第二个索引是字符串,则可以:

In [26]: s
Out[26]: 
0   a   -0.126299
1   a    1.810928
5   a    0.571873
0   b   -0.116108
1   b   -0.712184
2   b   -1.771264
4   b    0.148961
50  b    0.089683
0   c   -0.582578

In [25]: s[0]['a':'b']
Out[25]: 
a   -0.126299
b   -0.116108

Tags: inimportnumpypandaslenasnprandom
3条回答

我能想到的最好方法是在这种情况下使用“select”。尽管它甚至在文档中说“只有在没有更直接的方法时才应该使用这种方法。”

Indexing and selecting data

In [116]: s
Out[116]: 
a  0     1.724372
   1     0.305923
   5     1.780811
b  0    -0.556650
   1     0.207783
   4    -0.177901
   50    0.289365
   0     1.168115

In [117]: s.select(lambda x: x[0] == 'b' and 2 <= x[1] <= 10)
Out[117]: b  4   -0.177901

作为Robbie-Clarken answers,由于0.14,您可以传递slice in the tuple you pass to loc

In [11]: s.loc[('b', slice(2, 10))]
Out[11]:
b  2   -0.65394
   4    0.08227
dtype: float64

实际上,您可以为每个级别传递一个片段:

In [12]: s.loc[(slice('a', 'b'), slice(2, 10))]
Out[12]:
a  5    0.27919
b  2   -0.65394
   4    0.08227
dtype: float64

注意:切片是包含的。


旧答案:

您还可以使用以下方法执行此操作:

s.ix[1:10, "b"]

(在单个ix/loc/iloc中执行是一个很好的实践,因为这个版本允许赋值。)

这个答案是在2013年初的introduction of iloc之前写的,也就是位置/整数位置-在这种情况下可能是首选。创建它的原因是为了消除整数索引pandas对象的模糊性,并且更具描述性:“我在位置上切片”。

s["b"].iloc[1:10]

也就是说,我有点不同意那些文件,即ix是:

most robust and consistent way

不是,最一致的方式是描述你在做什么:

  • 对标签使用loc
  • 使用iloc定位
  • 两者都使用ix(如果真的需要的话)

记住zen of python

explicit is better than implicit

从pandas 0.14.0开始,可以通过提供包含slice对象的.loc元组来slice multi-indexed objects

In [2]: s.loc[('b', slice(2, 10))]
Out[2]:
b  2   -1.206052
   4   -0.735682
dtype: float64

相关问题 更多 >