Python 将索引和值排序与top-K选择相结合

Python 将索引和值排序与top-K选择相结合,python,pandas,Python,Pandas,假设我有一个包含列a、B、C和数据的数据框 我想: 将其转换为具有索引a、B和C 按此数据帧的索引A和B对行进行排序 在索引的每个AB对中,根据列数据上的值对行(即C索引)进行排序 根据前面的数据排序,获取每个AB对中的前20行 这应该不难,但我尝试过各种方法,但没有一种能满足我的需求。例如,下面的内容很接近,但它只给出了第一组AB索引的值 temp = mdf.set_index(['A', 'B','C']).sort_index() # Sorting by value and retr

假设我有一个包含列
a
B
C
数据的数据框

我想:

  • 将其转换为具有索引
    a
    B
    C
  • 按此数据帧的索引A和B对行进行排序
  • 在索引的每个
    A
    B
    对中,根据列
    数据上的值对行(即
    C
    索引)进行排序
  • 根据前面的数据排序,获取每个
    A
    B
    对中的前20行
  • 这应该不难,但我尝试过各种方法,但没有一种能满足我的需求。例如,下面的内容很接近,但它只给出了第一组
    A
    B
    索引的值

    temp = mdf.set_index(['A', 'B','C']).sort_index()
    
    # Sorting by value and retrieving the top 20 entries:
    func = lambda x: x.sort('data', ascending=False).head(20)
    temp = temp.groupby(level=['A','B'],as_index=False).apply(func)
    
    # Drop the dummy index (?) introduced in the line above
    temp = temp.reset_index(level=0)['data'] 
    
    更新: 例如,对于我要查找的内容(显示前3个元素),请注意数据在每个
    A-B
    对中的排序方式):


    我不确定我100%理解你想要什么,但我认为这可以做到。重置时,它将保持相同的顺序。关键是
    sortlevel()
    ,它按词汇顺序对级别(以及领带上的其余级别)进行排序。在0.14(即将推出)中,他们是一个选项,我想你可以使用它

    In [48]: np.random.seed(1234)
    
    In [49]:  df = pd.DataFrame({'A' : [np.random.random_integers(10) for x in xrange(500)], 
       ....:                      'B' : [np.random.random_integers(10) for x in xrange(500)], 
       ....:                      'C' : [np.random.random_integers(10) for x in xrange(500)],
       ....:                      'data' : randn(500) })
    
    首先设置索引,然后对其排序并重置

    然后按A、B分组,选出前20个最大的元素

    df.set_index(['A','B','C']).sortlevel().reset_index().groupby(
                 ['A','B']).apply(lambda x: x.sort(columns='data',ascending=False).head(20)).set_index(['A','B','C'])
    Out[8]: 
                 data
    A B  C           
    1 1  1   0.959688
         2   0.918230
         2   0.731919
         10  0.212463
         1   0.103644
         1  -0.035266
      2  8   1.459579
         8   1.277935
         5  -0.075886
         2  -0.684101
         3  -0.928110
      3  5   0.675987
         4   0.065301
         5  -0.800067
         7  -1.349503
      4  4   1.167308
         8   1.148327
         9   0.417590
         6  -1.274146
         10 -2.656304
      5  2  -0.962994
         1  -0.982679
      6  2   1.410920
         6   1.352527
         10  0.510330
         4   0.033275
         1  -0.679686
         10 -0.896797
         1  -2.858669
      7  8  -0.219342
         8  -0.591054
         2  -0.773227
         1  -0.781850
         3  -1.259089
         10 -1.387992
         10 -1.891734
      8  7   1.578855
         2  -0.498898
      9  3   0.644277
         8   0.572177
         2   0.058431
         9  -0.146912
         4  -0.334690
      10 9   0.795346
         8  -0.137661
         10 -1.335385
    2 1  9   1.309405
         3   0.328546
         5   0.198422
         1  -0.561974
         3  -0.578069
      2  5   0.645426
         1  -0.138808
         5  -0.400199
         5  -0.513738
         10 -0.667343
         9  -1.983470
      3  3   1.210882
         6   0.894201
         3   0.743652
                  ...
    
    [500 rows x 1 columns]
    

    我不确定我100%理解你想要什么,但我认为这可以做到。重置时,它将保持相同的顺序。关键是
    sortlevel()
    ,它按词汇顺序对级别(以及领带上的其余级别)进行排序。在0.14(即将推出)中,他们是一个选项,我想你可以使用它

    In [48]: np.random.seed(1234)
    
    In [49]:  df = pd.DataFrame({'A' : [np.random.random_integers(10) for x in xrange(500)], 
       ....:                      'B' : [np.random.random_integers(10) for x in xrange(500)], 
       ....:                      'C' : [np.random.random_integers(10) for x in xrange(500)],
       ....:                      'data' : randn(500) })
    
    首先设置索引,然后对其排序并重置

    然后按A、B分组,选出前20个最大的元素

    df.set_index(['A','B','C']).sortlevel().reset_index().groupby(
                 ['A','B']).apply(lambda x: x.sort(columns='data',ascending=False).head(20)).set_index(['A','B','C'])
    Out[8]: 
                 data
    A B  C           
    1 1  1   0.959688
         2   0.918230
         2   0.731919
         10  0.212463
         1   0.103644
         1  -0.035266
      2  8   1.459579
         8   1.277935
         5  -0.075886
         2  -0.684101
         3  -0.928110
      3  5   0.675987
         4   0.065301
         5  -0.800067
         7  -1.349503
      4  4   1.167308
         8   1.148327
         9   0.417590
         6  -1.274146
         10 -2.656304
      5  2  -0.962994
         1  -0.982679
      6  2   1.410920
         6   1.352527
         10  0.510330
         4   0.033275
         1  -0.679686
         10 -0.896797
         1  -2.858669
      7  8  -0.219342
         8  -0.591054
         2  -0.773227
         1  -0.781850
         3  -1.259089
         10 -1.387992
         10 -1.891734
      8  7   1.578855
         2  -0.498898
      9  3   0.644277
         8   0.572177
         2   0.058431
         9  -0.146912
         4  -0.334690
      10 9   0.795346
         8  -0.137661
         10 -1.335385
    2 1  9   1.309405
         3   0.328546
         5   0.198422
         1  -0.561974
         3  -0.578069
      2  5   0.645426
         1  -0.138808
         5  -0.400199
         5  -0.513738
         10 -0.667343
         9  -1.983470
      3  3   1.210882
         6   0.894201
         3   0.743652
                  ...
    
    [500 rows x 1 columns]
    

    我不确定我100%理解你想要什么,但我认为这可以做到。重置时,它将保持相同的顺序。关键是
    sortlevel()
    ,它按词汇顺序对级别(以及领带上的其余级别)进行排序。在0.14(即将推出)中,他们是一个选项,我想你可以使用它

    In [48]: np.random.seed(1234)
    
    In [49]:  df = pd.DataFrame({'A' : [np.random.random_integers(10) for x in xrange(500)], 
       ....:                      'B' : [np.random.random_integers(10) for x in xrange(500)], 
       ....:                      'C' : [np.random.random_integers(10) for x in xrange(500)],
       ....:                      'data' : randn(500) })
    
    首先设置索引,然后对其排序并重置

    然后按A、B分组,选出前20个最大的元素

    df.set_index(['A','B','C']).sortlevel().reset_index().groupby(
                 ['A','B']).apply(lambda x: x.sort(columns='data',ascending=False).head(20)).set_index(['A','B','C'])
    Out[8]: 
                 data
    A B  C           
    1 1  1   0.959688
         2   0.918230
         2   0.731919
         10  0.212463
         1   0.103644
         1  -0.035266
      2  8   1.459579
         8   1.277935
         5  -0.075886
         2  -0.684101
         3  -0.928110
      3  5   0.675987
         4   0.065301
         5  -0.800067
         7  -1.349503
      4  4   1.167308
         8   1.148327
         9   0.417590
         6  -1.274146
         10 -2.656304
      5  2  -0.962994
         1  -0.982679
      6  2   1.410920
         6   1.352527
         10  0.510330
         4   0.033275
         1  -0.679686
         10 -0.896797
         1  -2.858669
      7  8  -0.219342
         8  -0.591054
         2  -0.773227
         1  -0.781850
         3  -1.259089
         10 -1.387992
         10 -1.891734
      8  7   1.578855
         2  -0.498898
      9  3   0.644277
         8   0.572177
         2   0.058431
         9  -0.146912
         4  -0.334690
      10 9   0.795346
         8  -0.137661
         10 -1.335385
    2 1  9   1.309405
         3   0.328546
         5   0.198422
         1  -0.561974
         3  -0.578069
      2  5   0.645426
         1  -0.138808
         5  -0.400199
         5  -0.513738
         10 -0.667343
         9  -1.983470
      3  3   1.210882
         6   0.894201
         3   0.743652
                  ...
    
    [500 rows x 1 columns]
    

    我不确定我100%理解你想要什么,但我认为这可以做到。重置时,它将保持相同的顺序。关键是
    sortlevel()
    ,它按词汇顺序对级别(以及领带上的其余级别)进行排序。在0.14(即将推出)中,他们是一个选项,我想你可以使用它

    In [48]: np.random.seed(1234)
    
    In [49]:  df = pd.DataFrame({'A' : [np.random.random_integers(10) for x in xrange(500)], 
       ....:                      'B' : [np.random.random_integers(10) for x in xrange(500)], 
       ....:                      'C' : [np.random.random_integers(10) for x in xrange(500)],
       ....:                      'data' : randn(500) })
    
    首先设置索引,然后对其排序并重置

    然后按A、B分组,选出前20个最大的元素

    df.set_index(['A','B','C']).sortlevel().reset_index().groupby(
                 ['A','B']).apply(lambda x: x.sort(columns='data',ascending=False).head(20)).set_index(['A','B','C'])
    Out[8]: 
                 data
    A B  C           
    1 1  1   0.959688
         2   0.918230
         2   0.731919
         10  0.212463
         1   0.103644
         1  -0.035266
      2  8   1.459579
         8   1.277935
         5  -0.075886
         2  -0.684101
         3  -0.928110
      3  5   0.675987
         4   0.065301
         5  -0.800067
         7  -1.349503
      4  4   1.167308
         8   1.148327
         9   0.417590
         6  -1.274146
         10 -2.656304
      5  2  -0.962994
         1  -0.982679
      6  2   1.410920
         6   1.352527
         10  0.510330
         4   0.033275
         1  -0.679686
         10 -0.896797
         1  -2.858669
      7  8  -0.219342
         8  -0.591054
         2  -0.773227
         1  -0.781850
         3  -1.259089
         10 -1.387992
         10 -1.891734
      8  7   1.578855
         2  -0.498898
      9  3   0.644277
         8   0.572177
         2   0.058431
         9  -0.146912
         4  -0.334690
      10 9   0.795346
         8  -0.137661
         10 -1.335385
    2 1  9   1.309405
         3   0.328546
         5   0.198422
         1  -0.561974
         3  -0.578069
      2  5   0.645426
         1  -0.138808
         5  -0.400199
         5  -0.513738
         10 -0.667343
         9  -1.983470
      3  3   1.210882
         6   0.894201
         3   0.743652
                  ...
    
    [500 rows x 1 columns]
    
    试试这个

    df.sort('data', ascending=False).set_index('C').groupby(['A', 'B']).data.head(3)
    
    它不是最可读的语法,但可以完成任务

    A  B  C
    1  1  9     1.380526
          1     0.903524
          7    -0.112363
       2  2     0.284057
          5     0.131392
          1     0.111512
    
    试试这个

    df.sort('data', ascending=False).set_index('C').groupby(['A', 'B']).data.head(3)
    
    它不是最可读的语法,但可以完成任务

    A  B  C
    1  1  9     1.380526
          1     0.903524
          7    -0.112363
       2  2     0.284057
          5     0.131392
          1     0.111512
    
    试试这个

    df.sort('data', ascending=False).set_index('C').groupby(['A', 'B']).data.head(3)
    
    它不是最可读的语法,但可以完成任务

    A  B  C
    1  1  9     1.380526
          1     0.903524
          7    -0.112363
       2  2     0.284057
          5     0.131392
          1     0.111512
    
    试试这个

    df.sort('data', ascending=False).set_index('C').groupby(['A', 'B']).data.head(3)
    
    它不是最可读的语法,但可以完成任务

    A  B  C
    1  1  9     1.380526
          1     0.903524
          7    -0.112363
       2  2     0.284057
          5     0.131392
          1     0.111512
    



    发布框架的原始创建(带有代码),这样复制粘贴就容易多了。谢谢@Jeff。我添加了一个函数来创建一个与我正在使用的数据帧类似的随机数据帧。您预期的输出没有C排序?@Jeff
    C
    是根据数据排序的,也就是说,它是我在
    a-B
    中使用的索引。哦,好的,那么在后面添加排序是非常简单的(尽管您的问题是说按C排序):)发布框架的原始创建(带有代码),这样复制粘贴就容易多了。谢谢@Jeff。我添加了一个函数来创建一个与我正在使用的数据帧类似的随机数据帧。您预期的输出没有C排序?@Jeff
    C
    是根据数据排序的,也就是说,它是我在
    a-B
    中使用的索引。哦,好的,那么在后面添加排序是非常简单的(尽管您的问题是说按C排序):)发布框架的原始创建(带有代码),这样复制粘贴就容易多了。谢谢@Jeff。我添加了一个函数来创建一个与我正在使用的数据帧类似的随机数据帧。您预期的输出没有C排序?@Jeff
    C
    是根据数据排序的,也就是说,它是我在
    a-B
    中使用的索引。哦,好的,那么在后面添加排序是非常简单的(尽管您的问题是说按C排序):)发布框架的原始创建(带有代码),这样复制粘贴就容易多了。谢谢@Jeff。我添加了一个函数来创建一个与我正在使用的数据帧类似的随机数据帧。您预期的输出没有C排序?@Jeff
    C
    是根据数据排序的,也就是说,它是我在
    a-B
    中使用的索引。哦,好的,那么在后面添加排序非常简单(您的问题是说按C排序):)谢谢。这非常接近。我希望得到一个多索引数据帧的输出,带有我在OP中提到的排序属性。如果我将索引重新设置为代码的后处理步骤,这不会破坏排序吗?我更新了OP,以显示我想要的前几个条目。好的,修改了答案;在apply FYIThanks中,您几乎可以执行任何操作。为什么在这种特殊情况下使用
    sortlevel()
    而不使用
    sort\u index()
    ?(即在您的答复中)仅供参考。我刚开始买这张票,谢谢。这非常接近。我希望得到一个多索引数据帧的输出,带有我在OP中提到的排序属性。如果我将索引重新设置为代码的后处理步骤,这不会破坏排序吗?我更新了OP,以显示我想要的前几个条目。好的,修改了答案;在apply FYIThanks中,您几乎可以执行任何操作。为什么在这种特殊情况下使用
    sortlevel()
    而不使用
    sort\u index()
    ?(即在您的an中)