Lewati ke konten utama

Indeks hierarkis, groupby, dan pandas

Dalam tutorial ini, Anda akan mempelajari tentang multi-indeks untuk pandas DataFrame dan bagaimana indeks tersebut muncul secara alami dari operasi groupby pada kumpulan data dunia nyata.
· 9 mnt Baca

Jelajahi bersama AI

Dalam tulisan sebelumnya, Anda melihat bagaimana operasi groupby muncul secara alami melalui prinsip split-apply-combine. Anda meninjau sebuah dataset berisi penilaian pengguna Netflix dan mengelompokkan baris berdasarkan tahun rilis film untuk menghasilkan gambar berikut:

pandas groupby

Ini dicapai dengan mengelompokkan berdasarkan satu kolom. Saya sempat menyebutkan bahwa Anda mungkin ingin mengelompokkan berdasarkan beberapa kolom, yang dalam hal ini DataFrame pandas yang dihasilkan akan memiliki multi-index atau indeks hierarkis. Dalam tulisan ini, Anda akan mempelajari apa itu indeks hierarkis dan melihat bagaimana indeks tersebut muncul saat mengelompokkan berdasarkan beberapa fitur data Anda. Anda dapat mempelajari lebih lanjut tentang semua konsep dan praktik ini di kursus Manipulating DataFrames with pandas kami.

Jadi pertama-tama: apa itu indeks hierarkis?

hierarchical index pandas

Indeks Hierarkis dan pandas DataFrame

Apa itu Indeks dari sebuah DataFrame?

Sebelum memperkenalkan indeks hierarkis, mari kita ingat kembali apa itu indeks pada pandas DataFrame. Indeks sebuah DataFrame adalah himpunan yang terdiri atas label untuk setiap baris. Mari lihat contohnya. Saya akan terlebih dahulu mengimpor dataset sintetis tentang aktivitas seorang siswa DataCamp bernama Ellie di DataCamp. Kolom-kolomnya adalah tanggal, bahasa pemrograman, dan jumlah latihan yang diselesaikan Ellie hari itu dalam bahasa tersebut. Muat datanya:

# Import pandas
import pandas as pd

# Load in data
df = pd.read_csv('data/user_ex_python.csv')
df
 

Jalankan dan edit kode dari Tutorial ini secara online

Jalankan kode
 datelanguageex_complete
02017-01-01python6
12017-01-02python5
22017-01-03python10

Anda dapat melihat Index di sisi kiri DataFrame dan bahwa index tersebut terdiri atas bilangan bulat. Ini adalah RangeIndex:

# Check out index
df.index
RangeIndex(start=0, stop=3, step=1)

Kita dapat menggunakan indeks ini untuk mengambil satu atau beberapa baris dari df:

# Slice and dice data
df.loc[:1]
 datelanguageex_complete
02017-01-01python6
12017-01-02python5

Namun, indeks ini tidak begitu informatif. Jika Anda akan memberi label pada baris-baris DataFrame, akan lebih baik jika label tersebut bermakna, jika memungkinkan. Dapatkah Anda melakukannya dengan dataset ini? Cara berpikir yang baik tentang tantangan ini adalah Anda menginginkan pengenal yang unik dan bermakna untuk setiap baris. Periksa kolom-kolomnya dan lihat apakah ada yang memenuhi kriteria ini. Perhatikan bahwa kolom date berisi tanggal yang unik sehingga masuk akal untuk memberi label setiap baris berdasarkan kolom tanggal. Artinya, Anda dapat menjadikan kolom date sebagai indeks DataFrame menggunakan metode .set_index() (catatan: inplace=True berarti Anda benar-benar mengubah DataFrame df secara langsung):

# Set new index
df.set_index(pd.DatetimeIndex(df['date']), inplace=True)
df
 datelanguageex_complete
date   
2017-01-012017-01-01python6
2017-01-022017-01-02python5
2017-01-032017-01-03python10

Ini kemudian memberi df sebuah DateTimeIndex:

# Check out new index
df.index
DatetimeIndex(['2017-01-01', '2017-01-02', '2017-01-03'], dtype='datetime64[ns]', name='date', freq=None)

Sekarang Anda dapat mengambil baris menggunakan DateTimeIndex yang telah dibuat:

# Slice and dice data w/ new index
df.loc['2017-01-02']
date           2017-01-02
language           python
ex_complete             5
Name: 2017-01-02 00:00:00, dtype: object

Perhatikan juga bahwa atribut .columns mengembalikan sebuah indeks yang berisi nama kolom dari df:

# Check out columns
df.columns
Index(['date', 'language', 'ex_complete'], dtype='object')

Ini bisa sedikit membingungkan karena ini menyatakan bahwa df.columns bertipe Index. Ini bukan berarti kolom-kolom tersebut adalah indeks DataFrame. Indeks dari df selalu diberikan oleh df.index. Lihat tutorial pandas DataFrames kami untuk mempelajari lebih lanjut tentang indeks. Sekarang saatnya berkenalan dengan indeks hierarkis.

Multi-index pada pandas DataFrame

Bagaimana jika kita memiliki beberapa bahasa dalam dataset kita, seperti yang ada di DataCamp? Coba lihat:

# Import and check out data
df = pd.read_csv('data/user_ex.csv')
df
 datelanguageex_complete
02017-01-01python6
12017-01-02python5
22017-01-03python10
32017-01-01r8
42017-01-02r8
52017-01-03r8

Setiap tanggal kini berkorelasi dengan beberapa baris, satu untuk tiap bahasa. Lihat, misalnya, bahwa tanggal '2017-01-02' muncul pada baris 1 dan 4, masing-masing untuk bahasa Python dan R. Dengan demikian tanggal tidak lagi secara unik menentukan baris. Namun, 'date' dan 'language' secara bersama-sama memang menentukan baris secara unik. Karena itu, kita gunakan keduanya sebagai indeks:

# Set index
df.set_index(['date', 'language'], inplace=True)
df
  ex_complete
datelanguage 
2017-01-01python6
2017-01-02python5
2017-01-03python10
2017-01-01r8
2017-01-02r8
2017-01-03r8

Anda kini telah membuat multi-index, atau indeks hierarkis (biasakan diri dengan kedua istilah ini karena keduanya digunakan secara bergantian), dan Anda dapat melihatnya dengan memeriksa indeks sebagai berikut:

# Check out multi-index
df.index
MultiIndex(levels=[['2017-01-01', '2017-01-02', '2017-01-03'], ['python', 'r']],
           labels=[[0, 1, 2, 0, 1, 2], [0, 0, 0, 1, 1, 1]],
           names=['date', 'language'])

Hal di atas memberi tahu Anda bahwa DataFrame df kini memiliki MultiIndex dengan dua level, yang pertama berdasarkan tanggal, yang kedua berdasarkan bahasa. Ingat bahwa sebelumnya Anda dapat mengambil potongan DataFrame menggunakan indeks dan aksesori .loc: df.loc['2017-01-02']. Untuk dapat melakukan slicing dengan multi-index, Anda perlu mengurutkan indeks terlebih dahulu:

# Sort index
df.sort_index(inplace=True)
df
  ex_complete
datelanguage 
2017-01-01python6
r8
2017-01-02python5
r8
2017-01-03python10
r8

Sekarang Anda dapat mengambil jumlah latihan R yang diselesaikan pada 2017-01-02 dengan meneruskan sebuah tuple ke aksesori .loc:

# Slice & dice your DataFrame
df.loc[('2017-01-02', 'r')]

ex_complete 8 Name: (2017-01-02, r), dtype: int64

Kapan dan mengapa menggunakan multi-index

Multi-index adalah alat yang kuat untuk analisis dan pengorganisasian data di pandas. Multi-index memungkinkan pengguna membuat indeks hierarkis, yang dapat digunakan untuk mengelompokkan dan mengagregasi data di berbagai dimensi. Multi-index sangat berguna saat bekerja dengan dataset kompleks yang memiliki beberapa tingkat pengelompokan, seperti data keuangan atau deret waktu.

Dengan membuat multi-index, pengguna dapat mengelompokkan data berdasarkan beberapa variabel sekaligus, yang dapat mengungkap wawasan yang mungkin tidak terlihat dari pengelompokan satu tingkat. Misalnya, multi-index dapat digunakan untuk mengelompokkan data sekaligus berdasarkan waktu dan lokasi, sehingga analis dapat memeriksa tren di wilayah tertentu dari waktu ke waktu.

Selain itu, multi-index dapat digunakan untuk memilih dan mensubset data secara efisien, karena indeks menyediakan cara yang nyaman untuk mengakses subset data tertentu. Secara keseluruhan, multi-index adalah alat yang ampuh untuk mengorganisasi, mengelompokkan, dan menganalisis dataset kompleks di pandas, dan merupakan hal yang esensial bagi setiap analis atau ilmuwan data yang bekerja dengan data hierarkis.

Sekarang Anda sudah mengetahui sedikit tentang indeks hierarkis (atau multi-indeks). Saatnya melihat bagaimana indeks tersebut muncul saat bekerja dengan objek groupby.

Indeks Hierarkis, objek groupby, dan Split-Apply-Combine

Dalam tulisan sebelumnya, kita mengeksplorasi objek groupby dan prinsip analitik data split-apply-combine menggunakan data Netflix. Mari penyegaran cepat dengan dataset berbeda, yaitu dataset tips yang tersemat di paket seaborn. 'Tips' berisi fitur seperti tip, total_bill, hari dalam seminggu, dan waktu dalam sehari. Pertama muat dan jelajahi datanya:

# Import and check out data
import seaborn as sns
tips = sns.load_dataset("tips")
tips.head()
 total_billtipsexsmokerdaytimesize
016.991.01FemaleNoSunDinner2
110.341.66MaleNoSunDinner3
221.013.50MaleNoSunDinner3
323.683.31MaleNoSunDinner2
424.593.61FemaleNoSunDinner4

Perhatikan bahwa indeks dari tips adalah sebuah RangeIndex:

# Check out index
tips.index
RangeIndex(start=0, stop=244, step=1)

Selalu membantu melakukan EDA visual sebelum terjun ke komputasi dan fungsi pairplot milik seaborn memungkinkan Anda mendapatkan gambaran semua variabel numerik:

# Import pyplot, figures inline, set style, plot pairplot
import matplotlib.pyplot as plt
%matplotlib inline
sns.set()
sns.pairplot(tips, hue='day');

different charts

Jika Anda ingin melihat bagaimana rata-rata tip berbeda antara 'perokok' dan 'bukan perokok', Anda dapat membagi DataFrame asli berdasarkan 'smoker' (menggunakan groupby), menerapkan fungsi 'mean' dan menggabungkan menjadi DataFrame baru:

# Get mean of smoker/non-smoker groups
df = tips.groupby('smoker').mean()
df
 total_billtipsize
smoker   
Yes20.7563443.0087102.408602
No19.1882782.9918542.668874

Indeks DataFrame df yang dihasilkan adalah kolom/fitur 'smoker' dari DataFrame 'tips' asli:

# Check out new index
df.index
CategoricalIndex(['Yes', 'No'], categories=['Yes', 'No'], ordered=False, name='smoker', dtype='category')

Jika diinginkan, Anda dapat me-reset indeks sehingga 'smoker' menjadi kolom pada DataFrame:

# Reset the index
df.reset_index()
 smokertotal_billtipsize
0Yes20.7563443.0087102.408602
1No19.1882782.9918542.668874

Sekarang saatnya mencari tahu bagaimana indeks hierarkis muncul dari split-apply-combine dan operasi groupby.

Pengelompokan ganda dan indeks hierarkis

Di atas, Anda mengelompokkan dataset tips berdasarkan fitur 'smoker'. Terkadang Anda perlu mengelompokkan sebuah dataset berdasarkan dua fitur. Misalnya, wajar untuk mengelompokkan dataset tips menjadi perokok/bukan perokok & makan malam/makan siang. Untuk melakukannya, Anda meneruskan nama kolom yang ingin dikelompokkan sebagai sebuah list:

# Group by two columns
df = tips.groupby(['smoker','time']).mean()
df
  total_billtipsize
smokertime   
YesLunch17.3991302.8343482.217391
Dinner21.8594293.0660002.471429
NoLunch17.0508892.6737782.511111
Dinner20.0956603.1268872.735849

Melihat tabel di atas, Anda mungkin dapat melihat bahwa 'smoker' dan 'time' keduanya adalah indeks dari df. Memang demikian dan masuk akal: jika pengelompokan berdasarkan 'smoker' menghasilkan indeks berupa kolom 'smoker' asli, maka pengelompokan berdasarkan dua kolom akan memberi Anda dua indeks. Periksa indeks untuk mengonfirmasi bahwa indeksnya bersifat hierarkis:

# Check out index
df.index
MultiIndex(levels=[['Yes', 'No'], ['Lunch', 'Dinner']],
           labels=[[0, 0, 1, 1], [0, 1, 0, 1]],
           names=['smoker', 'time'])

Dan benar. Anda kini dapat melakukan banyak hal bermanfaat, seperti mendapatkan jumlah pada tiap pengelompokan:

# Group by two features
tips.groupby(['smoker','time']).size()
smoker  time  
Yes     Lunch      23
        Dinner     70
No      Lunch      45
        Dinner    106
dtype: int64

Anda juga dapat menukar level dari indeks hierarkis sehingga 'time' muncul sebelum 'smoker' di indeks:

# Swap levels of multi-index
df.swaplevel()
  total_billtipsize
timesmoker   
LunchYes17.3991302.8343482.217391
DinnerYes21.8594293.0660002.471429
LunchNo17.0508892.6737782.511111
DinnerNo20.0956603.1268872.735849

Anda kemudian mungkin ingin menghapus salah satu fitur ini dari indeks hierarkis dan membentuk kolom yang berbeda terhadap fitur tersebut. Anda dapat melakukannya dengan metode unstack:

# Unstack your multi-index
df.unstack()
 total_billtipsize
timeLunchDinnerLunchDinnerLunchDinner
smoker      
Yes17.39913021.8594292.8343483.0660002.2173912.471429
No17.05088920.0956602.6737783.1268872.5111112.735849

Anda dapat melakukan unstack pada fitur terluar dari indeks menggunakan argumen kata kunci 'level':

# Unsstack the outer index
df.unstack(level=0)
 total_billtipsize
smokerYesNoYesNoYesNo
time      
Lunch17.39913017.0508892.8343482.6737782.2173912.511111
Dinner21.85942920.0956603.0660003.1268872.4714292.735849

Hasil unstacking memiliki indeks non-hierarkis, seperti yang mungkin Anda harapkan:

# Check out index
df.unstack().index
CategoricalIndex(['Yes', 'No'], categories=['Yes', 'No'], ordered=False, name='smoker', dtype='category')

Akibatnya, Anda kini dapat melakukan berbagai jenis analisis data terkait pengelompokan ini. Saya mendorong Anda untuk mencobanya.

Indeks Hierarkis dalam Penggunaan Sehari-hari

Dalam tulisan ini, Anda diperkenalkan pada indeks hierarkis (atau multi-indeks) dan telah melihat bagaimana indeks tersebut muncul sebagai konsekuensi alami dari keinginan agar indeks DataFrame memberi label baris secara unik dan bermakna. Anda juga telah melihat bagaimana indeks tersebut muncul saat Anda perlu mengelompokkan data berdasarkan beberapa kolom, menerapkan prinsip split-apply-combine. Semoga Anda bersenang-senang dengan indeks hierarkis dalam pekerjaan Anda.

Tulisan ini dihasilkan dari Jupyter Notebook; Anda dapat menemukannya di repositori ini. Jika Anda memiliki pemikiran, tanggapan, dan/atau renungan, jangan ragu untuk menghubungi saya di Twitter: @hugobowne.

Lihat tutorial pandas DataCamp lainnya yang bermanfaat, termasuk:

Topik

Terkait

blogs

Tutorial Korelasi di R

blogs

Spaghetti Plot dan Jalur Badai

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026