Saya mencoba menyoroti apa yang berubah di antara dua kerangka data.
Misalkan saya memiliki dua kerangka data Python Pandas:
"StudentRoster Jan-1":
id Name score isEnrolled Comment
111 Jack 2.17 True He was late to class
112 Nick 1.11 False Graduated
113 Zoe 4.12 True
"StudentRoster Jan-2":
id Name score isEnrolled Comment
111 Jack 2.17 True He was late to class
112 Nick 1.21 False Graduated
113 Zoe 4.12 False On vacation
Tujuan saya adalah menampilkan tabel HTML yang:
- Identifikasi baris yang telah berubah (bisa int, float, boolean, string)
Output baris dengan nilai yang sama, TUA dan BARU (idealnya ke dalam tabel HTML) sehingga konsumen dapat dengan jelas melihat apa yang berubah antara dua kerangka data:
"StudentRoster Difference Jan-1 - Jan-2": id Name score isEnrolled Comment 112 Nick was 1.11| now 1.21 False Graduated 113 Zoe 4.12 was True | now False was "" | now "On vacation"
Saya kira saya bisa melakukan perbandingan baris per baris dan kolom, tetapi apakah ada cara yang lebih mudah?
df.compare
.Jawaban:
Bagian pertama mirip dengan Constantine, Anda bisa mendapatkan boolean yang barisnya kosong *:
Lalu kita bisa melihat entri mana yang telah berubah:
Di sini entri pertama adalah indeks dan kolom kedua yang telah diubah.
* Catatan: penting
df1
dandf2
bagikan indeks yang sama di sini. Untuk mengatasi ambiguitas ini, Anda dapat memastikan Anda hanya melihat label yang dibagikan menggunakandf1.index & df2.index
, tapi saya pikir saya akan meninggalkan itu sebagai latihan.sumber
df1
ke apa pun yang pertama masukdf2
, terlepas dari nilai indeks. JFYI kalau-kalau aku bukan satu-satunya orang yang ini tidak jelas. ; D Terima kasih!nan
di df1 dan df1, fungsi ini akan melaporkannya sebagai telah berubah darinan
menjadinan
. Ini karenanp.nan != np.nan
pengembalianTrue
.Menyoroti perbedaan antara dua DataFrames
Dimungkinkan untuk menggunakan properti gaya DataFrame untuk menyorot warna latar belakang sel di mana ada perbedaan.
Menggunakan contoh data dari pertanyaan awal
Langkah pertama adalah menyatukan DataFrames secara horizontal dengan
concat
fungsi dan membedakan setiap frame dengankeys
parameter:Mungkin lebih mudah untuk menukar level kolom dan menempatkan nama kolom yang sama di samping satu sama lain:
Sekarang, jauh lebih mudah untuk menemukan perbedaan dalam bingkai. Tapi, kita bisa melangkah lebih jauh dan menggunakan
style
properti untuk menyorot sel yang berbeda. Kami menetapkan fungsi khusus untuk melakukan ini yang dapat Anda lihat di bagian dokumentasi ini .Ini akan menyoroti sel-sel yang keduanya memiliki nilai yang hilang. Anda dapat mengisinya atau memberikan logika tambahan sehingga tidak disorot.
sumber
df_final[(df != df2).any(1)].style.apply(highlight_diff, axis=None)
Jawaban ini hanya memperpanjang @Andy Hayden, membuatnya tangguh ketika bidang numerik
nan
, dan membungkusnya menjadi fungsi.Jadi dengan data Anda (sedikit diedit untuk memiliki NaN di kolom skor):
Keluaran:
sumber
cetakan
sumber
id
sebagai indeks, makadf.groupby(level='id')
menimbulkan kesalahan, dan saya tidak yakin mengapa ...Saya telah menghadapi masalah ini, tetapi menemukan jawaban sebelum menemukan posting ini:
Berdasarkan jawaban unutbu, muat data Anda ...
... tentukan fungsi diff Anda ...
Kemudian Anda cukup menggunakan Panel untuk menyimpulkan:
Omong-omong, jika Anda menggunakan IPython Notebook, Anda mungkin ingin menggunakan fungsi diff berwarna untuk memberikan warna tergantung apakah sel-selnya berbeda, sama atau nol kiri / kanan:
sumber
my_panel = pd.Panel(dict(df1=df1,df2=df2))
di dalam fungsireport_diff()
? Maksud saya, apakah mungkin untuk melakukan ini:print report_diff(df1,df2)
dan mendapatkan hasil yang sama dengan pernyataan cetak Anda?pd.Panel(dict(df1=df1,df2=df2)).apply(report_diff, axis=0)
- ini luar biasa !!!Jika dua kerangka data Anda memiliki id yang sama di dalamnya, maka mencari tahu apa yang berubah sebenarnya cukup mudah. Hanya melakukan
frame1 != frame2
akan memberi Anda DataFrame boolean di mana masingTrue
- masing adalah data yang telah berubah. Dari itu, Anda bisa dengan mudah mendapatkan indeks dari setiap baris yang diubah dengan melakukanchangedids = frame1.index[np.any(frame1 != frame2,axis=1)]
.sumber
Pendekatan berbeda menggunakan concat dan drop_duplicates:
Keluaran:
sumber
Setelah mengutak-atik jawaban @ journois, saya bisa membuatnya bekerja menggunakan MultiIndex bukan Panel karena deprication Panel .
Pertama, buat beberapa data dummy:
Kemudian, tentukan fungsi dif Anda , dalam hal ini saya akan menggunakan yang dari jawabannya
report_diff
tetap sama:Lalu, saya akan menggabungkan data ke dalam kerangka data MultiIndex:
Dan akhirnya saya akan menerapkan ke
report_diff
bawah setiap grup kolom:Output ini:
Dan itu saja!
sumber
Memperluas jawaban @cge, yang cukup keren untuk hasil yang lebih mudah dibaca:
Contoh demonstrasi lengkap:
sumber
Berikut cara lain menggunakan select dan gabung:
Ini hal yang sama dari tangkapan layar Jupyter:
sumber
panda> = 1.1:
DataFrame.compare
Dengan panda 1.1, Anda pada dasarnya dapat mereplikasi keluaran Ted Petrou dengan satu panggilan fungsi. Contoh yang diambil dari dokumen:
Di sini, "diri" mengacu pada dataFrame LHS, sedangkan "lainnya" adalah DataFrame RHS. Secara default, nilai yang sama diganti dengan NaN sehingga Anda dapat fokus hanya pada perbedaan. Jika Anda ingin menunjukkan nilai yang sama juga, gunakan
Anda juga dapat mengubah sumbu perbandingan menggunakan
align_axis
:Ini membandingkan nilai baris-bijaksana, bukan kolom-bijaksana.
sumber
Fungsi yang menemukan perbedaan asimetris antara dua frame data diimplementasikan di bawah ini: (Berdasarkan set perbedaan untuk panda ) GIST: https://gist.github.com/oneryalcin/68cf25f536a25e65f0b3c84f9c118e03
Contoh:
sumber
panda impor sebagai pd impor numpy sebagai np
df = pd.read_excel ('D: \ HARISH \ DATA SCIENCE \ 1 MY Training \ SAMPEL DATA & projs \ DATA CRICKET \ DAFTAR PEMAIN IPL \ DAFTAR PEMAIN IPL \ DAFTAR PEMAIN IPL _ harish.xlsx')
df1 = srh = df [df ['TEAM']. str.contains ("SRH")] df2 = csk = df [df ['TEAM']. str.contains ("CSK")]
srh = srh.iloc [:, 0: 2] csk = csk.iloc [:, 0: 2]
csk = csk.reset_index (drop = True) csk
srh = srh.reset_index (drop = True) srh
baru = pd.concat ([srh, csk], axis = 1)
new.head ()
** JENIS PEMAIN JENIS PEMAIN
0 David Warner Batsman ... MS Dhoni Captain
1 Bhuvaneshwar Kumar Bowler ... Ravindra Jadeja All-Rounder
2 Manish Pandey Batsman ... Suresh Raina All-Rounder
3 Rashid Khan Arman Bowler ... Kedar Jadhav All-Rounder
4 Shikhar Dhawan Batsman .... Dwayne Bravo All-Rounder
sumber