2015-09-13 6 views
3

У меня есть многоуровневый индекс pandas DataFrame, где первый уровень year, а второй уровень - username. У меня есть только один столбец, который уже отсортирован по убыванию. Я хочу показать первые 2 строки каждого уровня индекса 0.Показать первые 10 строк мультииндекса данных pandas

Что я имею:

   count 
year username     
2010 b   677 
    a   505 
    c   400 
    d   300 
... 
2014 a   100 
    b   80 

Я хочу:

   count 
year username     
2010 b   677 
    a   505 
2011 c   677 
    d   505 
2012 e   677 
    f   505 
2013 g   677 
    i   505 
2014 h   677 
    j   505 
+0

При вызове 'головка (2)' на вашем GroupBy она должна дать вам первые 2 строки в каждой группе – EdChum

+0

Почему метки '['h', 'j']' для 2014 в ожидаемом выходе, а не '['a', 'b']'? –

ответ

3

Вот ответ. Может быть, есть лучший способ сделать это (с индексированием?), Но я знаю, что это работает. Принцип кажется сложным, но это довольно просто:

  • Индексирование DataFrame годом и имя пользователя.
  • Группы DataFrame в году, который является первым уровнем (=0) индекса
  • Применить две операции на вспомогательном DataFrame полученного groupby (один на каждый год)
    • сортировки индекса по количеству в по возрастанию sort_index(by='count') -> строки с большим количеством отсчетов будет в хвосте DataFrame
    • держать только последние строки top (2 в данном случае) с помощью отрицательной нарезки обозначения ([-top:]). Метод tail также может использоваться (tail(top)) для улучшения удобочитаемости.
  • Бросив ненужный уровень, созданный для droplevel(0) года

# Test data  
df = pd.DataFrame({'year': [2010, 2010, 2010, 2011,2011,2011, 2012, 2012, 2013, 2013, 2014, 2014], 
        'username': ['b','a','a','c','c','d','e','f','g','i','h','j'], 
        'count': [400, 505, 678, 677, 505, 505, 677, 505, 677, 505, 677, 505]}) 
df = df.set_index(['year','username']) 

top = 2 
df = df.groupby(level=0).apply(lambda df: df.sort_index(by='count')[-top:]) 
df.index = df.index.droplevel(0) 
df 

       count 
year username  
2010 a   505 
    a   678 
2011 d   505 
    c   677 
2012 f   505 
    e   677 
2013 i   505 
    g   677 
2014 j   505 
    h   677 
+0

Это потрясающе, это сработало. Теперь, если я только понял, что делает этот код ... – David

+0

@David Я добавил несколько объяснений, надеюсь, что они помогут. – Romain

+0

Иди в то же самое, ваш ответ был огромной помощью. Плюс к вам и вопрос оба. Кстати, вы когда-нибудь пробовали делать это через '.xs()'?У меня было несколько штук, и я не мог этого сделать. –

1

Если у вас есть гигантский фрейм данных вы не можете захотеть сделать groupby только, чтобы получить представление о данных. Вот еще одно решение для получения первых пяти строк внешнего индекса и первых двух строк внутреннего индекса.

df = pd.DataFrame({'year': [2010, 2010, 2010, 2011,2011,2011, 2012, 2012, 2013, 2013, 2014, 2014], 
       'username': ['b','a','a','c','c','d','e','f','g','i','h','j'], 
       'count': [400, 505, 678, 677, 505, 505, 677, 505, 677, 505, 677, 505]}) 
df = df.set_index(['year','username']) 

Обратите внимание, что DataFrame должен быть отсортирован.

df = df.sort_index(level=[0,1]) 

df 
       count 
year username  
2010 a  505 
     a  678 
     b  400 
2011 c  677 
     c  505 
     d  505 
2012 e  677 
     f  505 
2013 g  677 
     i  505 
2014 h  677 
     j  505 

Теперь для магии:

def head_mi(df, n1=5, n2=2): 

    #get top n of outer index 
    top_lev_0 = df.index.levels[0].values[:n1] 

    #get top n of inner index 
    top_lev_1 = [df.loc[ind].index.values[:n2] for ind in top_lev_0 ] 
    #top_lev_1 is a list of the inner index values 

    #iterate over outer index and get slice from inner index 
    acc = [] 
    for count0, ind0 in enumerate(top_lev_0): 
     acc.append(df.loc[(top_lev_0[count0], slice(top_lev_1[count0][0], top_lev_1[count0][-1])),:]) 

    return pd.concat(acc) 

head_mi(df) 

Это дает:

   count 
year username  
2010 a  505 
     a  678 
2011 c  677 
     c  505 
2012 e  677 
     f  505 
2013 g  677 
     i  505 
2014 h  677 
     j  505 
Смежные вопросы