Как создать мультииндексный фрейм данных, отсортированный по размеру группы? - PullRequest
2 голосов
/ 10 ноября 2019

У меня есть такой фрейм данных:

df = pd.DataFrame({
    'IDs': list('abcdefgh'),
    'Val': [
        'foo', 'bar', 'foo', 'abc', 'bar', 'bar', 'foo', 'foo'
    ]
})

  IDs  Val
0   a  foo
1   b  bar
2   c  foo
3   d  abc
4   e  bar
5   f  bar
6   g  foo
7   h  foo

Теперь я хочу получить такой вывод:

Val IDs           
foo a            
    c            
    g            
    h            
bar b            
    e            
    f            
abc d

Итак, это индекс мультииндексного фрейма данных, которыйупорядочен в соответствии с size каждой группы в Val.

В настоящее время я делаю это так:

df['groupsize'] = df.groupby('Val')['IDs'].transform('size')

df = (
    df.sort_values(['groupsize', 'Val', 'IDs'], ascending=[False, True, True])
      .drop('groupsize', axis=1)
      .set_index(['Val', 'IDs'])
)

df.to_excel('example.xlsx', merge_cells=True)

, что дает желаемый результат.

Есть ли способ достичь того же результата, но без создания этого промежуточного столбца groupsize, который все равно будет отброшен позже?

Ответы [ 2 ]

1 голос
/ 10 ноября 2019

Используйте set_index и value_counts

df.set_index('Val').loc[df.Val.value_counts().index]

Out[44]:
    IDs
Val
foo   a
foo   c
foo   g
foo   h
bar   b
bar   e
bar   f
abc   d

Если вам нужен мультииндекс, просто добавьте цепочку set_index с append=True

df.set_index('Val').loc[df.Val.value_counts().index].set_index('IDs', append=True)
1 голос
/ 10 ноября 2019

Вы можете использовать np.argsort и iloc, чтобы избежать многословия sort_values

s = np.argsort(-df.groupby('Val')['IDs'].transform('size'))

df.iloc[s].set_index(['Val', 'IDs'])

Val IDs
foo a
    c
    g
    h
bar b
    e
    f
abc d
...