Apa argumen 'level', 'keys', dan nama untuk di fungsi concat Pandas?

97

Pertanyaan

  • Bagaimana cara saya menggunakan pd.concat?
  • Untuk apa levelsargumennya?
  • Untuk apa keysargumennya?
  • Apakah ada banyak contoh untuk membantu menjelaskan cara menggunakan semua argumen?

concatFungsi panda adalah pisau Swiss Army untuk penggabungan utilitas. Berbagai situasi yang berguna sangat banyak. Dokumentasi yang ada meninggalkan beberapa detail tentang beberapa argumen opsional. Diantaranya adalah argumen levelsdan keys. Saya berangkat untuk mencari tahu apa yang dilakukan argumen tersebut.

Saya akan mengajukan pertanyaan yang akan bertindak sebagai pintu gerbang ke banyak aspek pd.concat.

Pertimbangkan data frame d1, d2dan d3:

import pandas as pd

d1 = pd.DataFrame(dict(A=.1, B=.2, C=.3), [2, 3])
d2 = pd.DataFrame(dict(B=.4, C=.5, D=.6), [1, 2])
d3 = pd.DataFrame(dict(A=.7, B=.8, D=.9), [1, 3])

Jika saya menggabungkan ini bersama-sama dengan

pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'])

Saya mendapatkan hasil yang diharapkan dengan a pandas.MultiIndexuntuk columnsobjek saya :

        A    B    C    D
d1 2  0.1  0.2  0.3  NaN
   3  0.1  0.2  0.3  NaN
d2 1  NaN  0.4  0.5  0.6
   2  NaN  0.4  0.5  0.6
d3 1  0.7  0.8  NaN  0.9
   3  0.7  0.8  NaN  0.9

Namun, saya ingin menggunakan levelsdokumentasi argumen :

level : daftar urutan, default Tidak ada. Tingkat spesifik (nilai unik) yang digunakan untuk membangun MultiIndex. Jika tidak, mereka akan disimpulkan dari kunci.

Jadi saya lulus

pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'], levels=[['d1', 'd2']])

Dan dapatkan a KeyError

ValueError: Key d3 not in level Index(['d1', 'd2'], dtype='object')

Ini masuk akal. Level yang saya lewati tidak memadai untuk menggambarkan level yang diperlukan yang ditunjukkan oleh tombol. Seandainya saya tidak lulus apa pun, seperti yang saya lakukan di atas, levelnya disimpulkan (seperti yang dinyatakan dalam dokumentasi). Tapi bagaimana lagi saya bisa menggunakan argumen ini untuk efek yang lebih baik?

Jika saya mencoba ini sebagai gantinya:

pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'], levels=[['d1', 'd2', 'd3']])

Saya dan mendapatkan hasil yang sama seperti di atas. Tapi saat saya menambahkan satu nilai lagi ke level,

df = pd.concat([d1, d2, d3], keys=['d1', 'd2', 'd3'], levels=[['d1', 'd2', 'd3', 'd4']])

Saya berakhir dengan bingkai data yang tampak sama, tetapi hasilnya MultiIndexmemiliki level yang tidak terpakai.

df.index.levels[0]

Index(['d1', 'd2', 'd3', 'd4'], dtype='object')

Jadi apa gunanya levelargumen dan haruskah saya menggunakan secara keysberbeda?

Saya menggunakan Python 3.6 dan Pandas 0.22.

piRSquared
sumber

Jawaban:

129

Dalam proses menjawab pertanyaan ini untuk diri saya sendiri, saya belajar banyak hal, dan saya ingin mengumpulkan katalog contoh dan penjelasan.

Jawaban spesifik dari levelsargumen 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 Seriesatau DataFrameobjek.
  • Saya akan menunjukkan bahwa itu dictbisa sangat berguna juga.
  • Generator juga dapat digunakan dan dapat berguna saat digunakan mapseperti dimap(f, list_of_df)

Untuk saat ini, kami akan tetap menggunakan daftar beberapa objek DataFramedan yang Seriesditentukan di atas. Saya akan menunjukkan bagaimana kamus dapat dimanfaatkan untuk memberikan MultiIndexhasil 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 axisyang nilai defaultnya adalah 0:

sumbu : {0 / 'indeks', 1 / 'kolom'}, default 0 Sumbu yang akan digabung.

Dua DataFramed dengan axis=0(ditumpuk)

Untuk nilai 0atau indexkami bermaksud mengatakan: "Sejajarkan sepanjang kolom dan tambahkan ke indeks".

Seperti yang ditunjukkan di atas di mana kami menggunakan axis=0, karena 0adalah nilai default, dan kami melihat bahwa indeks d2memperluas indeks d1meskipun 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 DataFrames dengan axis=1(berdampingan)

Untuk nilai 1atau columnskami 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 d1kolom d2.

Dua (atau Tiga) Seriesdengan axis=0(ditumpuk)

Saat menggabungkan pandas.Seriesbersama axis=0, kami mendapatkan kembali a pandas.Series. Nama yang dihasilkan Seriesakan menjadi Nonekecuali semua Seriesyang digabungkan memiliki nama yang sama. Perhatikan 'Name: A'kapan kita mencetak hasilnya Series. Jika tidak ada, kita bisa menganggap Seriesnamanya 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) Seriesdengan axis=1(berdampingan)

Saat menggabungkan pandas.Seriesbersama axis=1, itu adalah nameatribut 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 Seriesdan DataFramedengan axis=0(ditumpuk)

Saat melakukan penggabungan a Seriesdan DataFramebersama axis=0, kami mengonversi semua Seriesmenjadi satu kolom DataFrames.

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 Serieskolom 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_framesendiri.

Namun, saya dapat mengontrol nama kolom yang dihasilkan dengan parameter ke to_frame. Mengganti nama Seriesdengan renamemetode tidak mengontrol nama kolom dalam hasil DataFrame.

 # Effectively renames       |                            |
 # `s1` but does not align   |  # Does not rename.  So    |  # Renames to something
 # with columns in `d1`      |  # Pandas defaults to `0`  |  # that does align with `d1`
 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 Seriesdan DataFramedengan axis=1(berdampingan)

Ini cukup intuitif. Seriesnama kolom default ke pencacahan Seriesobjek tersebut ketika nameatribut 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 joinyang 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 leftatau rightkarena pd.concatdapat menangani lebih dari dua objek untuk digabungkan.

Dalam kasus d1dan 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 leftpenggabungan 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 d1di 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 Seriesobjek axis=0(memperluas indeks).

Kunci tersebut, menjadi level awal baru dari sebuah MultiIndexobjek di atribut index.

 #           length 3             length 3           #         length 2        length 2
 #          /--------\         /-----------\         #          /----\         /------\
 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 keysargumen untuk membuat argumen yang lebih dalam MultiIndex. Di sini kita melewati tuplespanjang 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 keysbertindak sebagai MultiIndexlevel di samping indeks yang ada. Sebab axis=1, kita mengacu pada sumbu yang Seriestidak dimiliki objek, yaitu columnsatribut.

Variasi Dua Seriesdenganaxis=1

Perhatikan bahwa penamaan s1dan s2masalah selama tidak keysdilewatkan, tetapi akan diganti jika keysdilewatkan.

               |                       |                        |  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
MultiIndexdengan Seriesdanaxis=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 DataFramedenganaxis=1

Seperti pada axis=0contoh, keystambahkan level ke a MultiIndex, tapi kali ini ke objek yang disimpan di columnsatribut.

 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
Seriesdan DataFramedenganaxis=1

Ini rumit. Dalam kasus ini, nilai kunci skalar tidak dapat bertindak sebagai satu-satunya tingkat indeks untuk Seriesobjek ketika menjadi kolom sementara juga bertindak sebagai tingkat pertama a MultiIndexuntuk DataFrame. Jadi Pandas akan kembali menggunakan nameatribut Seriesobjek 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 keysdan MultiIndexkesimpulan.

Pandas hanya tampaknya menyimpulkan nama kolom dari Seriesnama, 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 MultiIndexobjek 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 dictbukan alist

Saat mengoper kamus, pandas.concatakan menggunakan kunci dari kamus sebagai keysparameter.

 # axis=0               |  # axis=1
 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 keysargumen. Saat levelsdibiarkan sebagai nilai defaultnya None, Pandas akan mengambil nilai unik dari setiap level yang dihasilkan MultiIndexdan menggunakannya sebagai objek yang digunakan dalam index.levelsatribut 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, levelsargumennya adalah daftar urutan. Ini berarti kita dapat menggunakan yang lain pandas.Indexsebagai salah satu urutan tersebut.

Pertimbangkan bingkai data dfyang merupakan rangkaian dari d1, d2dan 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 sumdalam groupbykita 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 Thirddan Fifth? Dan saya ingin mereka dimasukkan dalam hasil groupbyagregasi? Kami dapat melakukan ini jika kami memiliki file pandas.CategoricalIndex. Dan kita dapat menentukannya sebelumnya dengan levelsargumen.

Jadi, mari kita definisikan dfsebagai:

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 groupbypenjumlahan 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 namesdaftar harus sesuai dengan jumlah level yang dihasilkan MultiIndex.

names : list, default None
Names untuk tingkat dalam indeks hierarki yang dihasilkan

 # axis=0                     |  # axis=1
 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 d1dan d2tidak 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]

piRSquared
sumber
23
akan jauh lebih berguna bagi komunitas jika hanya melakukan pull request untuk menambahkan beberapa contoh yang hilang (hanya beberapa) ke dokumen utama; SO hanya dapat dicari dan tidak dapat dijelajahi; lebih lanjut menempatkan tautan ke dokumen akan berguna di sini - sebagian besar sudah terdokumentasi dengan baik dan lengkap
Jeff
6
@Jeff ada dimensi pertumbuhan saya yang lambat. Menggunakan git adalah salah satunya. Saya berjanji itulah yang ingin saya mulai lakukan.
piRSquared
Menggunakan pd.concat(..., levels=[lvl]).groupby(axis=1, level=0).sum()menghasilkan hasil yang berbeda dari pd.concat(..., levels=[cats]).groupby(axis=1, level=0).sum(). Apa kamu tahu kenapa? Dokumen hanya mengatakan levelsharus daftar urutan.
unutbu
1
Jawaban yang bagus, tapi saya rasa bagian tentang Passing a dict instead of a listmembutuhkan contoh menggunakan dict, bukan daftar.
unutbu
1
@unutbu saya sudah perbaiki dictcontohnya, thx. Alasan mengapa itu lvladalah indeks kategorikal dan catshanya daftar. Saat mengelompokkan menurut tipe kategorikal, kategori yang hilang diisi dengan nol dan nol jika sesuai. Lihat ini
piRSquared