Python Pandas通过二级索引(或任何其他级别)切片多索引

rau*_*sch 8 python sorting slice multi-index pandas

关于将多索引的级别[0]切换为级别1的范围有很多帖子.但是,我无法找到解决问题的方法; 也就是说,我需要level [0]索引值的1级索引范围

dataframe:首先是A到Z,Rank是1到400; 我需要每个级别[0](第一个)的前2个和后2个,但不是在同一个步骤中.

           Title Score
First Rank 
A     1    foo   100
      2    bar   90
      3    lime  80
      4    lame  70
B     1    foo   400
      2    lime  300
      3    lame  200
      4    dime  100
Run Code Online (Sandbox Code Playgroud)

我试图用下面的代码获取每个1级索引的最后2行,但它仅适用于第一级[0]值.

[IN]  df.ix[x.index.levels[1][-2]:]
[OUT] 
               Title Score
    First Rank 
    A     3    lime  80
          4    lame  70
    B     1    foo   400
          2    lime  300
          3    lame  200
          4    dime  100
Run Code Online (Sandbox Code Playgroud)

我通过交换索引得到的前两行,但我不能使它适用于最后两行.

df.index = df.index.swaplevel("Rank", "First")
df= df.sortlevel() #to sort by Rank
df.ix[1:2] #Produces the first 2 ranks with 2 level[1] (First) each.
           Title Score
Rank First 
1     A    foo   100
      B    foo   400
2     A    bar   90
      B    lime  300
Run Code Online (Sandbox Code Playgroud)

当然我可以换回来得到这个:

df2 = df.ix[1:2]
df2.index = ttt.index.swaplevel("First","rank") #change the order of the indices back.
df2.sortlevel()
               Title Score
    First Rank 
    A     1    foo   100
          2    bar   90
    B     1    foo   400
          2    lime  300
Run Code Online (Sandbox Code Playgroud)

任何帮助都赞赏使用相同的程序:

  • 索引1的最后2行(Rank)
  • 并获得前两行的更好方法

编辑@ako的以下反馈:

使用pd.IndexSlice真正可以轻松切片任何级别索引.这是一个更通用的解决方案,下面是我逐步获取第一行和最后两行的方法.更多信息请访问:http://pandas.pydata.org/pandas-docs/stable/advanced.html#using-slicers

"""    
Slicing a dataframe at the level[2] index of the
major axis (row) for specific and at the level[1] index for columns.

"""
    df.loc[idx[:,:,['some label','another label']],idx[:,'yet another label']]

"""
Thanks to @ako below is my solution, including how I
get the top and last 2 rows.
"""
    idx = pd.IndexSlice
    # Top 2
    df.loc[idx[:,[1,2],:] #[1,2] is NOT a row index, it is the rank label. 
    # Last 2
    max = len(df.index.levels[df.index.names.index("rank")]) # unique rank labels
    last2=[x for x in range(max-2,max)]
    df.loc[idx[:,last2],:] #for last 2 - assuming all level[0] have the same lengths.
Run Code Online (Sandbox Code Playgroud)

ako*_*ako 14

使用索引器以任意维度切片任意值 - 只需传递一个列表,其中包含该维度所需的任何级别/值.

idx = pd.IndexSlice
df.loc[idx[:,[3,4]],:]

           Title  Score
First Rank             
A     3     lime     80
      4     lame     70
B     3     lame    200
      4     dime    100
Run Code Online (Sandbox Code Playgroud)

用于复制数据:

from StringIO import StringIO

s="""
First Rank Title Score
A      1    foo   100
A      2    bar   90
A      3    lime  80
A      4    lame  70
B      1    foo   400
B      2    lime  300
B      3    lame  200
B      4    dime  100
"""
df = pd.read_csv(StringIO(s),
                 sep='\s+',
                 index_col=["First", "Rank"])
Run Code Online (Sandbox Code Playgroud)

  • 通过StackOverflow对MultiIndex Pandas进行索引的答案,这个解决方案似乎都是最干净且非常低估的. (2认同)

Ash*_*Ash 7

在多级索引中按第二(子)级切片的另一种方法是使用slice(None)with .loc[]。使用slice(None)for a level 表示未对特定索引进行切片,然后为正在切片的索引传递单个项目或列表。希望对未来的读者有所帮助

df.loc[ ( slice(None), [3, 4] ),  : ]
Run Code Online (Sandbox Code Playgroud)