Pandas Datenrahmen erhalten die erste Zeile jeder Gruppe

137

Ich habe einen Pandas DataFramewie folgt.

df = pd.DataFrame({'id' : [1,1,1,2,2,3,3,3,3,4,4,5,6,6,6,7,7],
                'value'  : ["first","second","second","first",
                            "second","first","third","fourth",
                            "fifth","second","fifth","first",
                            "first","second","third","fourth","fifth"]})

Ich möchte dies nach ["id", "value"] gruppieren und die erste Zeile jeder Gruppe erhalten.

        id   value
0        1   first
1        1  second
2        1  second
3        2   first
4        2  second
5        3   first
6        3   third
7        3  fourth
8        3   fifth
9        4  second
10       4   fifth
11       5   first
12       6   first
13       6  second
14       6   third
15       7  fourth
16       7   fifth

Erwartetes Ergebnis

    id   value
     1   first
     2   first
     3   first
     4  second
     5  first
     6  first
     7  fourth

Ich habe versucht zu folgen, was nur die erste Zeile der gibt DataFrame. Jede Hilfe hierzu ist willkommen.

In [25]: for index, row in df.iterrows():
   ....:     df2 = pd.DataFrame(df.groupby(['id','value']).reset_index().ix[0])
Nilani Algiriyage
quelle
2
Mir ist klar, dass diese Frage ziemlich alt ist, aber ich würde vorschlagen, die Antwort von @vital_dml zu akzeptieren, da das Verhalten in first()Bezug auf nans sehr überraschend ist und etwas, von dem ich denke, dass die meisten Leute es nicht erwarten werden.
user545424

Antworten:

236
>>> df.groupby('id').first()
     value
id        
1    first
2    first
3    first
4   second
5    first
6    first
7   fourth

Wenn Sie idals Spalte benötigen :

>>> df.groupby('id').first().reset_index()
   id   value
0   1   first
1   2   first
2   3   first
3   4  second
4   5   first
5   6   first
6   7  fourth

Um n erste Datensätze zu erhalten, können Sie head () verwenden:

>>> df.groupby('id').head(2).reset_index(drop=True)
    id   value
0    1   first
1    1  second
2    2   first
3    2  second
4    3   first
5    3   third
6    4  second
7    4   fifth
8    5   first
9    6   first
10   6  second
11   7  fourth
12   7   fifth
Roman Pekar
quelle
1
Vielen Dank! Hat gut funktioniert :) Es ist nicht möglich, die zweite Reihe auf die gleiche Weise zu bekommen, oder? Kannst du es auch einfach erklären?
Nilani Algiriyage
g = df.groupby (['session']) g.agg (lambda x: x.iloc [0]) das funktioniert auch, keine ahnung den zweiten wert zu bekommen? :(
Nilani Algiriyage
Angenommen, Sie möchten von oben zählen, um die Zeilennummer top_n zu erhalten, dann dx = df.groupby ('id'). head (top_n) .reset_index (drop = True), und Sie möchten von unten zählen, um die Zeilennummer zu erhalten bottom_n, dann dx = df.groupby ('id'). tail (bottom_n) .reset_index (drop = True)
Quetzalcoatl
3
Wenn Sie die letzten n Zeilen möchten, verwenden Sie tail(n)(Standard ist n = 5) ( Ref. ). Nicht zu verwechseln last(), ich habe diesen Fehler gemacht.
Rocarvaj
groupby('id',as_index=False)hält auch idals Kolumne
Richard DiSalvo
50

Dies gibt Ihnen die zweite Zeile jeder Gruppe (null indiziert, n-te (0) ist die gleiche wie first ()):

df.groupby('id').nth(1) 

Dokumentation: http://pandas.pydata.org/pandas-docs/stable/groupby.html#taking-the-nth-row-of-each-group

wij
quelle
8
Wenn Sie Vielfache wie die ersten drei möchten, verwenden Sie eine Sequenz wie nth((0,1,2))oder nth(range(3)).
Ronan Paixão
@ RonanPaixão: Irgendwie, wenn ich Reichweite gebe, wirft es einen Fehler:TypeError: n needs to be an int or a list/set/tuple of ints
Friedlicher
@ Friedlich: Verwenden Sie Python 3? Wenn ja, range(3)wird keine Liste zurückgegeben, es sei denn, Sie geben ein list(range(3)).
Ben
41

Ich würde vorschlagen, .nth(0)eher zu verwenden, als .first()wenn Sie die erste Zeile erhalten müssen.

Der Unterschied zwischen ihnen ist , wie sie NaNs handhaben , so .nth(0)wird die erste Zeile der Gruppe zurückkehren , egal , was die Werte in dieser Reihe sind, während .first()schließlich die erste Rückkehr nicht NaN Wert in jeder Spalte.

ZB wenn Ihr Datensatz ist:

df = pd.DataFrame({'id' : [1,1,1,2,2,3,3,3,3,4,4],
            'value'  : ["first","second","third", np.NaN,
                        "second","first","second","third",
                        "fourth","first","second"]})

>>> df.groupby('id').nth(0)
    value
id        
1    first
2    NaN
3    first
4    first

Und

>>> df.groupby('id').first()
    value
id        
1    first
2    second
3    first
4    first
vital_dml
quelle
1
guter Punkt. .head(1)scheint sich auch so zu verhalten .nth(0), mit Ausnahme des Index
Richard DiSalvo
1
Ein weiterer Unterschied besteht darin, dass nth (0) den ursprünglichen Index beibehält (wenn as_index = False), first () jedoch nicht. Für mich war dies ein wesentlicher Unterschied, da ich den Index selbst benötigte.
Oleg O
7

Vielleicht ist es das, was du willst

import pandas as pd
idx = pd.MultiIndex.from_product([['state1','state2'],   ['county1','county2','county3','county4']])
df = pd.DataFrame({'pop': [12,15,65,42,78,67,55,31]}, index=idx)
                pop
state1 county1   12
       county2   15
       county3   65
       county4   42
state2 county1   78
       county2   67
       county3   55
       county4   31
df.groupby(level=0, group_keys=False).apply(lambda x: x.sort_values('pop', ascending=False)).groupby(level=0).head(3)

> Out[29]: 
                pop
state1 county3   65
       county4   42
       county2   15
state2 county1   78
       county2   67
       county3   55
Siraj S.
quelle
7

Wenn Sie nur die erste Zeile aus jeder Gruppe benötigen, mit der wir arbeiten können drop_duplicates, beachten Sie die Standardmethode der Funktion keep='first'.

df.drop_duplicates('id')
Out[1027]: 
    id   value
0    1   first
3    2   first
5    3   first
9    4  second
11   5   first
12   6   first
15   7  fourth
YOBEN_S
quelle