Bingkai data panda mendapatkan baris pertama dari setiap grup

137

Saya punya panda DataFrameseperti berikut.

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"]})

Saya ingin mengelompokkan ini berdasarkan ["id", "value"] dan mendapatkan baris pertama dari setiap grup.

        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

Hasil yang diharapkan

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

Saya mencoba mengikuti yang hanya memberikan baris pertama DataFrame. Setiap bantuan mengenai hal ini sangat kami hargai.

In [25]: for index, row in df.iterrows():
   ....:     df2 = pd.DataFrame(df.groupby(['id','value']).reset_index().ix[0])
Nilani Algiriyage
sumber
2
Saya menyadari pertanyaan ini sudah cukup lama, tetapi saya sarankan menerima jawaban oleh @vital_dml karena perilaku first()sehubungan dengan nans sangat mengejutkan dan sesuatu yang saya pikir kebanyakan orang tidak akan berharap.
user545424

Jawaban:

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

Jika Anda perlu idsebagai kolom:

>>> 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

Untuk mendapatkan n catatan pertama, Anda dapat menggunakan head ():

>>> 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
sumber
1
Terima kasih banyak! Bekerja dengan baik :) Tidak mungkin mendapatkan baris kedua dengan cara yang sama, bukan? Bisakah Anda menjelaskannya juga?
Nilani Algiriyage
g = df.groupby (['session']) g.agg (lambda x: x.iloc [0]) ini juga berfungsi, tidak ada ide untuk mendapatkan nilai kedua? :(
Nilani Algiriyage
misalkan menghitung dari atas Anda ingin mendapatkan nomor baris top_n, lalu dx = df.groupby ('id'). head (top_n) .reset_index (drop = True) dan anggap bahwa menghitung dari bawah Anda ingin mendapatkan nomor baris bottom_n, lalu dx = df.groupby ('id'). tail (bottom_n) .reset_index (drop = True)
Quetzalcoatl
3
Jika Anda menginginkan n baris terakhir, gunakan tail(n)(standarnya adalah n = 5) ( ref. ). Jangan bingung last(), saya membuat kesalahan itu.
rocarvaj
groupby('id',as_index=False)juga disimpan idsebagai kolom
Richard DiSalvo
50

Ini akan memberi Anda baris kedua dari setiap grup (nol diindeks, n (0) sama dengan pertama ()):

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

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

wij
sumber
8
Jika Anda ingin kelipatan, seperti tiga yang pertama, misalnya, gunakan urutan seperti nth((0,1,2))atau nth(range(3)).
Ronan Paixão
@ RonanPaixão: Entah bagaimana ketika saya memberikan jangkauan, itu melontarkan kesalahan:TypeError: n needs to be an int or a list/set/tuple of ints
Damai
@Peaceful: apakah Anda menggunakan Python 3? Jika demikian, range(3)jangan kembali daftar kecuali Anda mengetik list(range(3)).
Ben
41

Saya sarankan untuk menggunakan .nth(0)daripada .first()jika Anda perlu mendapatkan baris pertama.

Perbedaan di antara mereka adalah bagaimana mereka menangani NaN, jadi .nth(0)akan mengembalikan baris pertama grup, apa pun nilai di baris ini, sementara .first()pada akhirnya akan mengembalikan nilai bukan pertama NaNdi setiap kolom.

Misalnya jika dataset Anda adalah:

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

Dan

>>> df.groupby('id').first()
    value
id        
1    first
2    second
3    first
4    first
vital_dml
sumber
1
Poin yang bagus. .head(1)juga tampaknya berperilaku seperti .nth(0), kecuali untuk indeks
Richard DiSalvo
1
Perbedaan lainnya adalah bahwa n (0) akan mempertahankan indeks asli (jika as_index = Salah), sedangkan yang pertama () tidak akan. Sekali lagi bagi saya ini adalah perbedaan yang substansial, karena saya memerlukan indeks itu sendiri.
Oleg O
7

mungkin ini yang kamu inginkan

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.
sumber
7

Jika Anda hanya memerlukan baris pertama dari setiap grup yang dapat kami lakukan drop_duplicates, Perhatikan metode fungsi default 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
sumber