代码之家  ›  专栏  ›  技术社区  ›  Michael

熊猫:按外观顺序排序

  •  1
  • Michael  · 技术社区  · 5 年前

    假设我们有一个数据帧:

    df = pd.DataFrame(pd.np.zeros((15,10,)), dtype=int, \
        index=[['a']*5+['b']*5+['c']*5, list(range(15))])
    df.index.names=['index0', 'index1']
    pd.np.random.seed(0)
    for i, v in df.iterrows():
        v.loc[pd.np.random.randint(10)] = 1
    
    df
    
                   0  1  2  3  4  5  6  7  8  9
    index0 index1                              
    a      0       0  0  0  0  0  1  0  0  0  0
           1       1  0  0  0  0  0  0  0  0  0
           2       0  0  0  1  0  0  0  0  0  0
           3       0  0  0  1  0  0  0  0  0  0
           4       0  0  0  0  0  0  0  1  0  0
    b      5       0  0  0  0  0  0  0  0  0  1
           6       0  0  0  1  0  0  0  0  0  0
           7       0  0  0  0  0  1  0  0  0  0
           8       0  0  1  0  0  0  0  0  0  0
           9       0  0  0  0  1  0  0  0  0  0
    c      10      0  0  0  0  0  0  0  1  0  0
           11      0  0  0  0  0  0  1  0  0  0
           12      0  0  0  0  0  0  0  0  1  0
           13      0  0  0  0  0  0  0  0  1  0
           14      0  1  0  0  0  0  0  0  0  0
    

    如何先按“1”的出现顺序对A、B、C块中的行进行排序,然后再对A、B、C块进行排序?

    预期输出:

                   0  1  2  3  4  5  6  7  8  9
    index0 index1                              
    a      1       1  0  0  0  0  0  0  0  0  0
           2       0  0  0  1  0  0  0  0  0  0
           3       0  0  0  1  0  0  0  0  0  0
           0       0  0  0  0  0  1  0  0  0  0
           4       0  0  0  0  0  0  0  1  0  0
    c      14      0  1  0  0  0  0  0  0  0  0
           11      0  0  0  0  0  0  1  0  0  0
           10      0  0  0  0  0  0  0  1  0  0
           12      0  0  0  0  0  0  0  0  1  0
           13      0  0  0  0  0  0  0  0  1  0
    b      8       0  0  1  0  0  0  0  0  0  0
           6       0  0  0  1  0  0  0  0  0  0
           9       0  0  0  0  1  0  0  0  0  0
           7       0  0  0  0  0  1  0  0  0  0
           5       0  0  0  0  0  0  0  0  0  1
    

    编辑:值可以不是“1”,实际上这些是不同的文本值。

    1 回复  |  直到 5 年前
        1
  •  1
  •   Chris    5 年前

    一种方法是使用 pandas.DataFrame.groupby 具有 idxmax sort_values :

    import pandas as pd
    
    l = (d.loc[d.idxmax(1).sort_values().index] for _, d in df.groupby('index0'))
    new_df = pd.concat(sorted(l, key= lambda x:list(x.sum()), reverse=True))
    print(new_df)
    

    输出:

                   0  1  2  3  4  5  6  7  8  9
    index0 index1                              
    a      1       1  0  0  0  0  0  0  0  0  0
           2       0  0  0  1  0  0  0  0  0  0
           3       0  0  0  1  0  0  0  0  0  0
           0       0  0  0  0  0  1  0  0  0  0
           4       0  0  0  0  0  0  0  1  0  0
    c      14      0  1  0  0  0  0  0  0  0  0
           11      0  0  0  0  0  0  1  0  0  0
           10      0  0  0  0  0  0  0  1  0  0
           12      0  0  0  0  0  0  0  0  1  0
           13      0  0  0  0  0  0  0  0  1  0
    b      8       0  0  1  0  0  0  0  0  0  0
           6       0  0  0  1  0  0  0  0  0  0
           9       0  0  0  0  1  0  0  0  0  0
           7       0  0  0  0  0  1  0  0  0  0
           5       0  0  0  0  0  0  0  0  0  1
    

    以防 1 S是文本,其余部分相同,请尝试使用 pandas.Dataframe.ne

    tmp = df.ne(0)
    # same operation
    new_df = df.loc[new_tmp.index]