Saya membaca beberapa data cuaca otomatis dari web. Pengamatan terjadi setiap 5 menit dan dikompilasi ke dalam file bulanan untuk setiap stasiun cuaca. Setelah saya selesai mengurai file, DataFrame terlihat seperti ini:
Sta Precip1hr Precip5min Temp DewPnt WindSpd WindDir AtmPress
Date
2001-01-01 00:00:00 KPDX 0 0 4 3 0 0 30.31
2001-01-01 00:05:00 KPDX 0 0 4 3 0 0 30.30
2001-01-01 00:10:00 KPDX 0 0 4 3 4 80 30.30
2001-01-01 00:15:00 KPDX 0 0 3 2 5 90 30.30
2001-01-01 00:20:00 KPDX 0 0 3 2 10 110 30.28
Masalah yang saya alami adalah bahwa kadang-kadang seorang ilmuwan kembali dan mengoreksi pengamatan - bukan dengan mengedit baris yang salah, tetapi dengan menambahkan baris duplikat ke akhir file. Contoh sederhana dari kasus seperti ini diilustrasikan di bawah ini:
import pandas
import datetime
startdate = datetime.datetime(2001, 1, 1, 0, 0)
enddate = datetime.datetime(2001, 1, 1, 5, 0)
index = pandas.DatetimeIndex(start=startdate, end=enddate, freq='H')
data1 = {'A' : range(6), 'B' : range(6)}
data2 = {'A' : [20, -30, 40], 'B' : [-50, 60, -70]}
df1 = pandas.DataFrame(data=data1, index=index)
df2 = pandas.DataFrame(data=data2, index=index[:3])
df3 = df2.append(df1)
df3
A B
2001-01-01 00:00:00 20 -50
2001-01-01 01:00:00 -30 60
2001-01-01 02:00:00 40 -70
2001-01-01 03:00:00 3 3
2001-01-01 04:00:00 4 4
2001-01-01 05:00:00 5 5
2001-01-01 00:00:00 0 0
2001-01-01 01:00:00 1 1
2001-01-01 02:00:00 2 2
Jadi saya harus df3
menjadi:
A B
2001-01-01 00:00:00 0 0
2001-01-01 01:00:00 1 1
2001-01-01 02:00:00 2 2
2001-01-01 03:00:00 3 3
2001-01-01 04:00:00 4 4
2001-01-01 05:00:00 5 5
Saya pikir bahwa menambahkan kolom nomor baris ( df3['rownum'] = range(df3.shape[0])
) akan membantu saya pilih keluar paling bawah baris untuk setiap nilai DatetimeIndex
, tapi saya terjebak pada mencari tahu group_by
atau pivot
pernyataan (atau ???) untuk membuat pekerjaan itu.
Jawaban:
Saya akan menyarankan menggunakan metode duplikat pada Indeks Pandas itu sendiri:
Meskipun semua metode lain berfungsi, jawaban yang saat ini diterima adalah yang paling sedikit performan untuk contoh yang diberikan. Selain itu, walaupun metode groupby hanya sedikit performan, saya menemukan metode duplikat lebih mudah dibaca.
Menggunakan data sampel yang disediakan:
Perhatikan bahwa Anda dapat menyimpan elemen terakhir dengan mengubah argumen keep.
Juga harus dicatat bahwa metode ini juga berfungsi dengan
MultiIndex
baik (menggunakan df1 seperti yang ditentukan dalam contoh Paul ):sumber
loc
mungkin tidak perlu. Cukup lakukandf3 = df3[~df3.index.duplicated(keep='first')]
, yang akan menjatuhkan semua baris dengan indeks duplikat kecuali kejadian pertama.Solusi sederhana adalah menggunakan
drop_duplicates
Bagi saya, ini beroperasi dengan cepat pada set data besar.
Ini mengharuskan 'rownum' menjadi kolom dengan duplikat. Dalam contoh yang dimodifikasi, 'rownum' tidak memiliki duplikat, oleh karena itu tidak ada yang dihilangkan. Yang kami inginkan adalah agar 'cols' disetel ke indeks. Saya belum menemukan cara untuk memberi tahu drop_duplicates untuk hanya mempertimbangkan indeks.
Berikut adalah solusi yang menambahkan indeks sebagai kolom dataframe, menjatuhkan duplikat pada itu, lalu menghapus kolom baru:
Dan jika Anda ingin semuanya kembali dalam urutan yang tepat, panggil saja
sort
kerangka data.sumber
df.reset_index().drop_duplicates(cols='index',take_last=True).set_index('index')
reset_index()
tambahkan kolom level_0, level_1, dll. Dan jika indeks Anda memiliki nama, nama itu akan digunakan sebagai pengganti label "indeks". Itu membuat ini sedikit lebih dari satu-liner untuk melakukannya dengan benar untuk DataFrame apa pun.index_label = getattr(df.index, 'names', getattr(df.index, 'name', 'index'))
lalucols=index_label
kemudianset_index(index_labels)
dan bahkan ini tidak mudah (tidak akan bekerja untuk multiindex yang tidak disebutkan namanya).idx = df.index.name or 'index'
, orang juga bisa melakukandf2 = df.reset_index(); df2.drop_duplicates(idx, inplace=True); df2.set_index(idx, inplace=True)
untuk menghindari salinan perantara (karenainplace=True
)Astaga. Ini sebenarnya sangat sederhana!
Sunting lanjut 2013-10-29 Dalam kasus di mana saya memiliki yang cukup kompleks
MultiIndex
, saya pikir saya lebih sukagroupby
pendekatan. Inilah contoh sederhana untuk anak cucu:dan inilah bagian yang penting
sumber
level=[0,1]
akan berfungsi jika ada 2 leveldf1.groupby(level=[0,1]).last()
. Ini harus menjadi bagian dari Panda sebagaidrop_duplicates
df.index.names
hanyalah cara mudah untuk mengelompokkan berdasarkan semua level indeks.xarray
untuk berurusan dengan indeks DateTime duplikat juga yang membuatds.resample
dands.groupby
operasi gagalxarray
selama Anda mengubahgrouped = df3.groupby(level=0)
togrouped = df3.groupby(dim='time')
atau dimensi apa pun yang mengandung duplikatSayangnya, saya tidak berpikir Pandas memungkinkan seseorang untuk menjatuhkan dups dari indeks. Saya akan menyarankan yang berikut ini:
sumber
Jika ada orang seperti saya suka manipulasi data yang dapat di rantai menggunakan notasi titik panda (seperti perpipaan), maka hal berikut ini mungkin berguna:
Ini memungkinkan pernyataan rantai seperti ini:
sumber
TypeError: 'Series' objects are mutable, thus they cannot be hashed
.. Apakah ini benar-benar bekerja untuk Anda?Hapus duplikat (Keeping First)
Hapus duplikat (Menjaga Terakhir)
Pengujian: loop 10k menggunakan data OP
sumber