Dalam proses menjawab pertanyaan ini untuk diri saya sendiri, saya belajar banyak hal, dan saya ingin mengumpulkan katalog contoh dan penjelasan.
Jawaban spesifik dari levels
argumen akan sampai pada akhir.
pandas.concat
: Manual yang Hilang
Tautan ke Dokumentasi Saat Ini
Mengimpor dan menentukan objek
import pandas as pd
d1 = pd.DataFrame(dict(A=.1, B=.2, C=.3), index=[2, 3])
d2 = pd.DataFrame(dict(B=.4, C=.5, D=.6), index=[1, 2])
d3 = pd.DataFrame(dict(A=.7, B=.8, D=.9), index=[1, 3])
s1 = pd.Series([1, 2], index=[2, 3])
s2 = pd.Series([3, 4], index=[1, 2])
s3 = pd.Series([5, 6], index=[1, 3])
Argumen
objs
Argumen pertama yang kami temukan adalah objs
:
objs : urutan atau pemetaan objek Seri, DataFrame, atau Panel Jika dict dilewatkan, kunci yang diurutkan akan digunakan sebagai argumen kunci, kecuali jika dilewatkan, dalam hal ini nilainya akan dipilih (lihat di bawah). Objek None apa pun akan dijatuhkan secara diam-diam kecuali semuanya adalah None dalam hal ini ValueError akan dimunculkan
- Kami biasanya melihat ini digunakan dengan daftar
Series
atau DataFrame
objek.
- Saya akan menunjukkan bahwa itu
dict
bisa sangat berguna juga.
- Generator juga dapat digunakan dan dapat berguna saat digunakan
map
seperti dimap(f, list_of_df)
Untuk saat ini, kami akan tetap menggunakan daftar beberapa objek DataFrame
dan yang Series
ditentukan di atas. Saya akan menunjukkan bagaimana kamus dapat dimanfaatkan untuk memberikan MultiIndex
hasil yang sangat berguna nanti.
pd.concat([d1, d2])
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
axis
Argumen kedua yang kami temui adalah axis
yang nilai defaultnya adalah 0
:
sumbu : {0 / 'indeks', 1 / 'kolom'}, default 0 Sumbu yang akan digabung.
Dua DataFrame
d dengan axis=0
(ditumpuk)
Untuk nilai 0
atau index
kami bermaksud mengatakan: "Sejajarkan sepanjang kolom dan tambahkan ke indeks".
Seperti yang ditunjukkan di atas di mana kami menggunakan axis=0
, karena 0
adalah nilai default, dan kami melihat bahwa indeks d2
memperluas indeks d1
meskipun ada tumpang tindih nilai 2
:
pd.concat([d1, d2], axis=0)
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
Dua DataFrame
s dengan axis=1
(berdampingan)
Untuk nilai 1
atau columns
kami bermaksud mengatakan: "Sejajarkan sepanjang indeks dan tambahkan ke kolom",
pd.concat([d1, d2], axis=1)
A B C B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
Kita dapat melihat bahwa indeks yang dihasilkan adalah gabungan dari indeks dan kolom yang dihasilkan adalah perpanjangan dari kolom dari d1
kolom d2
.
Dua (atau Tiga) Series
dengan axis=0
(ditumpuk)
Saat menggabungkan pandas.Series
bersama axis=0
, kami mendapatkan kembali a pandas.Series
. Nama yang dihasilkan Series
akan menjadi None
kecuali semua Series
yang digabungkan memiliki nama yang sama. Perhatikan 'Name: A'
kapan kita mencetak hasilnya Series
. Jika tidak ada, kita bisa menganggap Series
namanya None
.
| | | pd.concat(
| pd.concat( | pd.concat( | [s1.rename('A'),
pd.concat( | [s1.rename('A'), | [s1.rename('A'), | s2.rename('B'),
[s1, s2]) | s2]) | s2.rename('A')]) | s3.rename('A')])
-------------- | --------------------- | ---------------------- | ----------------------
2 1 | 2 1 | 2 1 | 2 1
3 2 | 3 2 | 3 2 | 3 2
1 3 | 1 3 | 1 3 | 1 3
2 4 | 2 4 | 2 4 | 2 4
dtype: int64 | dtype: int64 | Name: A, dtype: int64 | 1 5
| | | 3 6
| | | dtype: int64
Dua (atau Tiga) Series
dengan axis=1
(berdampingan)
Saat menggabungkan pandas.Series
bersama axis=1
, itu adalah name
atribut yang kita rujuk untuk menyimpulkan nama kolom dalam hasil pandas.DataFrame
.
| | pd.concat(
| pd.concat( | [s1.rename('X'),
pd.concat( | [s1.rename('X'), | s2.rename('Y'),
[s1, s2], axis=1) | s2], axis=1) | s3.rename('Z')], axis=1)
---------------------- | --------------------- | ------------------------------
0 1 | X 0 | X Y Z
1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0 5.0
2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0 NaN
3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN 6.0
Dicampur Series
dan DataFrame
dengan axis=0
(ditumpuk)
Saat melakukan penggabungan a Series
dan DataFrame
bersama axis=0
, kami mengonversi semua Series
menjadi satu kolom DataFrame
s.
Perhatikan secara khusus bahwa ini adalah rangkaian bersama axis=0
; itu berarti memperluas indeks (baris) sambil meratakan kolom. Pada contoh di bawah ini, kita melihat index menjadi [2, 3, 2, 3]
yang merupakan penambahan indeks tanpa pandang bulu. Kolom tidak tumpang tindih kecuali saya memaksa penamaan Series
kolom dengan argumen ke to_frame
:
pd.concat( |
[s1.to_frame(), d1]) | pd.concat([s1, d1])
------------------------- | ---------------------
0 A B C | 0 A B C
2 1.0 NaN NaN NaN | 2 1.0 NaN NaN NaN
3 2.0 NaN NaN NaN | 3 2.0 NaN NaN NaN
2 NaN 0.1 0.2 0.3 | 2 NaN 0.1 0.2 0.3
3 NaN 0.1 0.2 0.3 | 3 NaN 0.1 0.2 0.3
Anda bisa melihat hasilnya pd.concat([s1, d1])
sama seperti jika saya telah melakukan to_frame
sendiri.
Namun, saya dapat mengontrol nama kolom yang dihasilkan dengan parameter ke to_frame
. Mengganti nama Series
dengan rename
metode tidak mengontrol nama kolom dalam hasil DataFrame
.
pd.concat( | pd.concat( | pd.concat(
[s1.to_frame('X'), d1]) | [s1.rename('X'), d1]) | [s1.to_frame('B'), d1])
---------------------------- | -------------------------- | ----------------------------
A B C X | 0 A B C | A B C
2 NaN NaN NaN 1.0 | 2 1.0 NaN NaN NaN | 2 NaN 1.0 NaN
3 NaN NaN NaN 2.0 | 3 2.0 NaN NaN NaN | 3 NaN 2.0 NaN
2 0.1 0.2 0.3 NaN | 2 NaN 0.1 0.2 0.3 | 2 0.1 0.2 0.3
3 0.1 0.2 0.3 NaN | 3 NaN 0.1 0.2 0.3 | 3 0.1 0.2 0.3
Dicampur Series
dan DataFrame
dengan axis=1
(berdampingan)
Ini cukup intuitif. Series
nama kolom default ke pencacahan Series
objek tersebut ketika name
atribut tidak tersedia.
| pd.concat(
pd.concat( | [s1.rename('X'),
[s1, d1], | s2, s3, d1],
axis=1) | axis=1)
------------------- | -------------------------------
0 A B C | X 0 1 A B C
2 1 0.1 0.2 0.3 | 1 NaN 3.0 5.0 NaN NaN NaN
3 2 0.1 0.2 0.3 | 2 1.0 4.0 NaN 0.1 0.2 0.3
| 3 2.0 NaN 6.0 0.1 0.2 0.3
join
Argumen ketiga adalah join
yang menjelaskan apakah gabungan yang dihasilkan harus gabungan luar (default) atau gabungan dalam.
join : {'inner', 'outer'}, default 'outer'
Bagaimana menangani indeks pada sumbu lain.
Ternyata, tidak ada opsi left
atau right
karena pd.concat
dapat menangani lebih dari dua objek untuk digabungkan.
Dalam kasus d1
dan d2
, opsinya terlihat seperti:
outer
pd.concat([d1, d2], axis=1, join='outer')
A B C B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
inner
pd.concat([d1, d2], axis=1, join='inner')
A B C B C D
2 0.1 0.2 0.3 0.4 0.5 0.6
join_axes
Argumen keempat adalah hal yang memungkinkan kita melakukan left
penggabungan dan lainnya.
join_axes : daftar objek Indeks Indeks
khusus yang akan digunakan untuk sumbu n - 1 lainnya daripada melakukan logika himpunan dalam / luar.
Gabung Kiri
pd.concat([d1, d2, d3], axis=1, join_axes=[d1.index])
A B C B C D A B D
2 0.1 0.2 0.3 0.4 0.5 0.6 NaN NaN NaN
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
Gabung Kanan
pd.concat([d1, d2, d3], axis=1, join_axes=[d3.index])
A B C B C D A B D
1 NaN NaN NaN 0.4 0.5 0.6 0.7 0.8 0.9
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
ignore_index
ignore_index : boolean, default False
Jika True, jangan gunakan nilai indeks di sepanjang sumbu penggabungan. Sumbu yang dihasilkan akan diberi label 0, ..., n - 1. Ini berguna jika Anda adalah objek penggabungan di mana sumbu penggabungan tidak memiliki informasi pengindeksan yang berarti. Perhatikan nilai indeks pada sumbu lain masih dihormati dalam gabungan.
Seperti ketika saya menumpuk d1
di atas d2
, jika saya tidak peduli dengan nilai indeks, saya dapat mengatur ulang atau mengabaikannya.
| pd.concat( | pd.concat(
| [d1, d2], | [d1, d2]
pd.concat([d1, d2]) | ignore_index=True) | ).reset_index(drop=True)
--------------------- | ----------------------- | -------------------------
A B C D | A B C D | A B C D
2 0.1 0.2 0.3 NaN | 0 0.1 0.2 0.3 NaN | 0 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN | 1 0.1 0.2 0.3 NaN | 1 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6 | 2 NaN 0.4 0.5 0.6 | 2 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6 | 3 NaN 0.4 0.5 0.6 | 3 NaN 0.4 0.5 0.6
Dan saat menggunakan axis=1
:
| pd.concat(
| [d1, d2], axis=1,
pd.concat([d1, d2], axis=1) | ignore_index=True)
------------------------------- | -------------------------------
A B C B C D | 0 1 2 3 4 5
1 NaN NaN NaN 0.4 0.5 0.6 | 1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6 | 2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN | 3 0.1 0.2 0.3 NaN NaN NaN
keys
Kita dapat mengirimkan daftar nilai skalar atau tupel untuk menetapkan nilai tupel atau skalar ke MultiIndex yang sesuai. Panjang daftar yang lolos harus sama dengan jumlah item yang digabungkan.
keys : sequence, default None
Jika melewati beberapa level, harus berisi tupel. Buat indeks hierarki menggunakan kunci yang diteruskan sebagai tingkat terluar
axis=0
Saat menggabungkan Series
objek axis=0
(memperluas indeks).
Kunci tersebut, menjadi level awal baru dari sebuah MultiIndex
objek di atribut index.
pd.concat([s1, s2, s3], keys=['A', 'B', 'C']) pd.concat([s1, s2], keys=['A', 'B'])
---------------------------------------------- -------------------------------------
A 2 1 A 2 1
3 2 3 2
B 1 3 B 1 3
2 4 2 4
C 1 5 dtype: int64
3 6
dtype: int64
Namun, kita dapat menggunakan lebih dari nilai skalar dalam keys
argumen untuk membuat argumen yang lebih dalam MultiIndex
. Di sini kita melewati tuples
panjang 2 prepend dua tingkat baru dari a MultiIndex
:
pd.concat(
[s1, s2, s3],
keys=[('A', 'X'), ('A', 'Y'), ('B', 'X')])
-----------------------------------------------
A X 2 1
3 2
Y 1 3
2 4
B X 1 5
3 6
dtype: int64
axis=1
Ini sedikit berbeda saat memperluas kolom. Ketika kami menggunakan axis=0
(lihat di atas) kami keys
bertindak sebagai MultiIndex
level di samping indeks yang ada. Sebab axis=1
, kita mengacu pada sumbu yang Series
tidak dimiliki objek, yaitu columns
atribut.
Variasi Dua
Series
dengan
axis=1
Perhatikan bahwa penamaan s1
dan s2
masalah selama tidak keys
dilewatkan, tetapi akan diganti jika keys
dilewatkan.
| | | pd.concat(
| pd.concat( | pd.concat( | [s1.rename('U'),
pd.concat( | [s1, s2], | [s1.rename('U'), | s2.rename('V')],
[s1, s2], | axis=1, | s2.rename('V')], | axis=1,
axis=1) | keys=['X', 'Y']) | axis=1) | keys=['X', 'Y'])
-------------- | --------------------- | ---------------------- | ----------------------
0 1 | X Y | U V | X Y
1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0 | 1 NaN 3.0
2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0 | 2 1.0 4.0
3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN | 3 2.0 NaN
MultiIndex
dengan
Series
dan
axis=1
pd.concat(
[s1, s2],
axis=1,
keys=[('W', 'X'), ('W', 'Y')])
-----------------------------------
W
X Y
1 NaN 3.0
2 1.0 4.0
3 2.0 NaN
Dua
DataFrame
dengan
axis=1
Seperti pada axis=0
contoh, keys
tambahkan level ke a MultiIndex
, tapi kali ini ke objek yang disimpan di columns
atribut.
pd.concat( | pd.concat(
[d1, d2], | [d1, d2],
axis=1, | axis=1,
keys=['X', 'Y']) | keys=[('First', 'X'), ('Second', 'X')])
------------------------------- | --------------------------------------------
X Y | First Second
A B C B C D | X X
1 NaN NaN NaN 0.4 0.5 0.6 | A B C B C D
2 0.1 0.2 0.3 0.4 0.5 0.6 | 1 NaN NaN NaN 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN | 2 0.1 0.2 0.3 0.4 0.5 0.6
| 3 0.1 0.2 0.3 NaN NaN NaN
Series
dan
DataFrame
dengan
axis=1
Ini rumit. Dalam kasus ini, nilai kunci skalar tidak dapat bertindak sebagai satu-satunya tingkat indeks untuk Series
objek ketika menjadi kolom sementara juga bertindak sebagai tingkat pertama a MultiIndex
untuk DataFrame
. Jadi Pandas akan kembali menggunakan name
atribut Series
objek sebagai sumber nama kolom.
pd.concat( | pd.concat(
[s1, d1], | [s1.rename('Z'), d1],
axis=1, | axis=1,
keys=['X', 'Y']) | keys=['X', 'Y'])
--------------------- | --------------------------
X Y | X Y
0 A B C | Z A B C
2 1 0.1 0.2 0.3 | 2 1 0.1 0.2 0.3
3 2 0.1 0.2 0.3 | 3 2 0.1 0.2 0.3
Batasan
keys
dan
MultiIndex
kesimpulan.
Pandas hanya tampaknya menyimpulkan nama kolom dari Series
nama, tetapi tidak akan mengisi kekosongan saat melakukan penggabungan analog antara bingkai data dengan jumlah level kolom yang berbeda.
d1_ = pd.concat(
[d1], axis=1,
keys=['One'])
d1_
One
A B C
2 0.1 0.2 0.3
3 0.1 0.2 0.3
Kemudian gabungkan ini dengan bingkai data lain dengan hanya satu tingkat di objek kolom dan Pandas akan menolak untuk mencoba dan membuat tupel MultiIndex
objek dan menggabungkan semua bingkai data seolah-olah satu tingkat objek, skalar, dan tupel.
pd.concat([d1_, d2], axis=1)
(One, A) (One, B) (One, C) B C D
1 NaN NaN NaN 0.4 0.5 0.6
2 0.1 0.2 0.3 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN NaN NaN
Mengoper dict
bukan alist
Saat mengoper kamus, pandas.concat
akan menggunakan kunci dari kamus sebagai keys
parameter.
pd.concat( | pd.concat(
{0: d1, 1: d2}) | {0: d1, 1: d2}, axis=1)
----------------------- | -------------------------------
A B C D | 0 1
0 2 0.1 0.2 0.3 NaN | A B C B C D
3 0.1 0.2 0.3 NaN | 1 NaN NaN NaN 0.4 0.5 0.6
1 1 NaN 0.4 0.5 0.6 | 2 0.1 0.2 0.3 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6 | 3 0.1 0.2 0.3 NaN NaN NaN
levels
Ini digunakan bersama dengan keys
argumen. Saat levels
dibiarkan sebagai nilai defaultnya None
, Pandas akan mengambil nilai unik dari setiap level yang dihasilkan MultiIndex
dan menggunakannya sebagai objek yang digunakan dalam index.levels
atribut yang dihasilkan .
level : daftar urutan, default Tidak ada
Level spesifik (nilai unik) yang digunakan untuk membangun MultiIndex. Jika tidak, mereka akan disimpulkan dari kunci.
Jika Panda sudah menyimpulkan berapa level yang seharusnya, apa keuntungan yang ada untuk menentukannya sendiri? Saya akan menunjukkan satu contoh dan menyerahkan kepada Anda untuk memikirkan alasan lain mengapa ini mungkin berguna.
Contoh
Menurut dokumentasi, levels
argumennya adalah daftar urutan. Ini berarti kita dapat menggunakan yang lain pandas.Index
sebagai salah satu urutan tersebut.
Pertimbangkan bingkai data df
yang merupakan rangkaian dari d1
, d2
dan d3
:
df = pd.concat(
[d1, d2, d3], axis=1,
keys=['First', 'Second', 'Fourth'])
df
First Second Fourth
A B C B C D A B D
1 NaN NaN NaN 0.4 0.5 0.6 0.7 0.8 0.9
2 0.1 0.2 0.3 0.4 0.5 0.6 NaN NaN NaN
3 0.1 0.2 0.3 NaN NaN NaN 0.7 0.8 0.9
Tingkatan dari objek kolom adalah:
print(df, *df.columns.levels, sep='\n')
Index(['First', 'Second', 'Fourth'], dtype='object')
Index(['A', 'B', 'C', 'D'], dtype='object')
Jika kita menggunakan sum
dalam groupby
kita dapatkan:
df.groupby(axis=1, level=0).sum()
First Fourth Second
1 0.0 2.4 1.5
2 0.6 0.0 1.5
3 0.6 2.4 0.0
Tetapi bagaimana jika bukannya ['First', 'Second', 'Fourth']
ada kategori lain yang hilang bernama Third
dan Fifth
? Dan saya ingin mereka dimasukkan dalam hasil groupby
agregasi? Kami dapat melakukan ini jika kami memiliki file pandas.CategoricalIndex
. Dan kita dapat menentukannya sebelumnya dengan levels
argumen.
Jadi, mari kita definisikan df
sebagai:
cats = ['First', 'Second', 'Third', 'Fourth', 'Fifth']
lvl = pd.CategoricalIndex(cats, categories=cats, ordered=True)
df = pd.concat(
[d1, d2, d3], axis=1,
keys=['First', 'Second', 'Fourth'],
levels=[lvl]
)
df
First Fourth Second
1 0.0 2.4 1.5
2 0.6 0.0 1.5
3 0.6 2.4 0.0
Tapi level pertama dari objek kolom adalah:
df.columns.levels[0]
CategoricalIndex(
['First', 'Second', 'Third', 'Fourth', 'Fifth'],
categories=['First', 'Second', 'Third', 'Fourth', 'Fifth'],
ordered=True, dtype='category')
Dan groupby
penjumlahan kami terlihat seperti:
df.groupby(axis=1, level=0).sum()
First Second Third Fourth Fifth
1 0.0 1.5 0.0 2.4 0.0
2 0.6 1.5 0.0 0.0 0.0
3 0.6 0.0 0.0 2.4 0.0
names
Ini digunakan untuk memberi nama level yang dihasilkan MultiIndex
. Panjang names
daftar harus sesuai dengan jumlah level yang dihasilkan MultiIndex
.
names : list, default None
Names untuk tingkat dalam indeks hierarki yang dihasilkan
pd.concat( | pd.concat(
[d1, d2], | [d1, d2],
keys=[0, 1], | axis=1, keys=[0, 1],
names=['lvl0', 'lvl1']) | names=['lvl0', 'lvl1'])
----------------------------- | ----------------------------------
A B C D | lvl0 0 1
lvl0 lvl1 | lvl1 A B C B C D
0 2 0.1 0.2 0.3 NaN | 1 NaN NaN NaN 0.4 0.5 0.6
3 0.1 0.2 0.3 NaN | 2 0.1 0.2 0.3 0.4 0.5 0.6
1 1 NaN 0.4 0.5 0.6 | 3 0.1 0.2 0.3 NaN NaN NaN
2 NaN 0.4 0.5 0.6 |
verify_integrity
Dokumentasi yang cukup jelas
verifikasi_integrity : boolean, default Salah
Periksa apakah sumbu gabungan baru berisi duplikat. Ini bisa sangat mahal dibandingkan dengan penggabungan data yang sebenarnya.
Karena indeks yang dihasilkan dari penggabungan d1
dan d2
tidak unik, pemeriksaan integritas akan gagal.
pd.concat([d1, d2])
A B C D
2 0.1 0.2 0.3 NaN
3 0.1 0.2 0.3 NaN
1 NaN 0.4 0.5 0.6
2 NaN 0.4 0.5 0.6
Dan
pd.concat([d1, d2], verify_integrity=True)
> ValueError: Indeks memiliki nilai yang tumpang tindih: [2]
pd.concat(..., levels=[lvl]).groupby(axis=1, level=0).sum()
menghasilkan hasil yang berbeda daripd.concat(..., levels=[cats]).groupby(axis=1, level=0).sum()
. Apa kamu tahu kenapa? Dokumen hanya mengatakanlevels
harus daftar urutan.Passing a dict instead of a list
membutuhkan contoh menggunakan dict, bukan daftar.dict
contohnya, thx. Alasan mengapa itulvl
adalah indeks kategorikal dancats
hanya daftar. Saat mengelompokkan menurut tipe kategorikal, kategori yang hilang diisi dengan nol dan nol jika sesuai. Lihat ini