import pandas as pd
= pd.Series([4, 7, -5, 3])
obj obj
0 4
1 7
2 -5
3 3
dtype: int64
Intro to Pandas
February 27, 2024
Kembali ke EDA
Library pada python adalah potongan kode yang reusable dan dapat kita akses dengan mengimpornya ke dalam program kita. Pada mata kuliah algoritma dan pemrograman yang telah kalian ambil di semester 1, telah diperkenalkan beberapa library yang dapat kalian import ke dalam script kalian seperti numpy, scipy, sympy, pandas, matplotlib dan lainnya.
Dalam bidang data analysis, library python yang umum digunakan adalah numpy
dan pandas
untuk pengolahan data tabular, matplotlib
dan seaborn
untuk visualisasi
Jika anda menggunakan jupyter notebook secara local pada perangkat anda, anda perlu menginstall 3 library tersebut untuk praktikum ini. Gunakan python package manager (pip) untuk menginstall library numpy
, pandas
, matplotlib
dan seaborn
dengan memanggil pip install <nama-library>
di terminal. Jika anda menggunakan conda atau google colab, library-library ini sudah terinstall secara otomatis dan dapat kita import secara langsung.
Untuk mengecek apakah library yang diperlukan sudah terinstall, run blok kode di bawah ini.
Jika library sudah terinstall, maka output akan menunjukkan versi dari library yang terinstall.
Pada dasarnya, pandas dibuat atas struktur data yang terdapat pada library NumPy yaitu Array. Array sendiri sudah pernah dibahas dalam mata kuliah algoritma dan pemrograman sehingga kita tidak akan mendalaminya pada praktikum ini.
Series adalah suatu object yang menyerupai array 1 dimensi yang memiliki nilai dengan array index yang berkaitan dengan masing-masing nilai.
kolom kiri adalah index, kolom kanan adalah Values (nilai).
Untuk mengakses values saja :
Untuk mengakses index saja :
Dengan Series kita bisa menggunakan index untuk mengakses value yang berkaitan dengan index tersebut.
d 0.25
b 0.50
a 0.75
c 1.00
dtype: float64
Perhatikan jumlah index harus sama dengan jumlah value yang ditetapkan.
Untuk mengubah index suatu series bisa juga dengan mengubah nilai <series>.index
Dictionary pada python adalah struktur data yang berisi pasangan key-value. Kita dapat melihat series sebagai pasangan key-value dengan index sebagai key. Bahkan kita bisa membuat suatu series dari sebuah dictionary.
{'Jakarta': 400, 'Bandung': 200, 'Bogor': 300, 'Depok': 500}
Jakarta 400
Bandung 200
Bogor 300
Depok 500
dtype: int64
Jika kita ingin index dengan urutan tertentu, maka kita dapat memasukkan argumen index berupa list index sesuai dengan urutan yang kita inginkan.
kota = ['Surabaya', 'Bandung', 'Bogor', 'Jakarta']
data_series2 = pd.Series(data_dict, index=kota)
data_series2
Surabaya NaN
Bandung 200.0
Bogor 300.0
Jakarta 400.0
dtype: float64
Perhatikan bahwa jika kita memasukkan index yang tidak ada pada dictionary awal, index akan dimasukkan dengan nilai NaN
(Not a Number)
Series secara otomatis menyamakan index ketika melakukan operasi aritmatika.
Bandung 400.0
Bogor 600.0
Depok NaN
Jakarta 800.0
Surabaya NaN
dtype: float64
Perhatikan bahwa Depok
dan Surabaya
bernilai NaN
. Hal ini dikarenakan kedua index tersebut tidak terdapat pada kedua series yang kita operasikan.
name
attributeDataFrame adalah struktur data 2 dimensi yang terdiri atas baris dan kolom (disebut juga tabel). Kita dapat melihat dataframe sebagai gabungan dari 2 atau lebih series.
Karena memiliki 2 dimensi (baris dan kolom), DataFrame memiliki indeks untuk masing-masing baris dan kolom.
Ada banyak cara untuk membangun DataFrame, salah satu yang paling umum adalah membuat dictionary dengan
data = {'kota': ['Bogor', 'Bogor', 'Bogor', 'Depok', 'Depok', 'Depok'],
'tahun': [2000, 2001, 2002, 2001, 2002, 2003],
'populasi': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
df = pd.DataFrame(data) # `df` adalah singkatan yang umum digunakan oleh komunitas python dalam mendefinisikan suatu `dataframe`
df
kota | tahun | populasi | |
---|---|---|---|
0 | Bogor | 2000 | 1.5 |
1 | Bogor | 2001 | 1.7 |
2 | Bogor | 2002 | 3.6 |
3 | Depok | 2001 | 2.4 |
4 | Depok | 2002 | 2.9 |
5 | Depok | 2003 | 3.2 |
pd.DataFrame()
menerima argumen columns=
yang dapat digunakan untuk menentukan urutan kolom dataframe.
tahun | kota | populasi | |
---|---|---|---|
0 | 2000 | Bogor | 1.5 |
1 | 2001 | Bogor | 1.7 |
2 | 2002 | Bogor | 3.6 |
3 | 2001 | Depok | 2.4 |
4 | 2002 | Depok | 2.9 |
5 | 2003 | Depok | 3.2 |
NaN
pd.DataFrame
juga menerima argumen index=
untuk mengubah index seperti pada pd.Series
df2 = pd.DataFrame(data, columns=['tahun', 'kota', 'populasi', 'luas_wilayah'],
index=['one', 'two', 'three', 'four', 'five', 'six'])
df2
tahun | kota | populasi | luas_wilayah | |
---|---|---|---|---|
one | 2000 | Bogor | 1.5 | NaN |
two | 2001 | Bogor | 1.7 | NaN |
three | 2002 | Bogor | 3.6 | NaN |
four | 2001 | Depok | 2.4 | NaN |
five | 2002 | Depok | 2.9 | NaN |
six | 2003 | Depok | 3.2 | NaN |
Dalam mengolah suatu data, tidaklah mungkin kita harus menulis ulang seluruh data yang sudah tertulis dengan format tertentu (misalnya Spreadsheet/.xlsx, .csv, atau .dat) pastinya kita perlu suatu cara untuk mengimpor data yang memiliki berbagai format. Pandas memiliki beberapa function yang dapat kita gunakan untuk membaca data dengan berbagai format.
Untuk tipe file lainnya, silahkan baca dokumentasi pandas di link berikut : Pandas IO Tools
Sejauh ini kita sudah berkenalan dengan 2 object pandas yaitu Series dan DataFrame. Dalam pemrograman python, sebuah object bisa memiliki suatu method, attribute/property, atau keduanya.
Untuk materi selanjutnya, kita akan menggunakan dataset pokemon sebagai contoh. Jalankan code block di bawah ini.
head()
Memanggil method head akan mengembalikan beberapa baris pertama dari suatu dataframe.
# | Name | Type 1 | Type 2 | HP | Attack | Defense | Sp. Atk | Sp. Def | Speed | Generation | Legendary | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | Bulbasaur | Grass | Poison | 45 | 49 | 49 | 65 | 65 | 45 | 1 | False |
1 | 2 | Ivysaur | Grass | Poison | 60 | 62 | 63 | 80 | 80 | 60 | 1 | False |
2 | 3 | Venusaur | Grass | Poison | 80 | 82 | 83 | 100 | 100 | 80 | 1 | False |
tail()
Memanggil method tail akan mengembalikan beberapa baris terakhir dari suatu dataframe.
# | Name | Type 1 | Type 2 | HP | Attack | Defense | Sp. Atk | Sp. Def | Speed | Generation | Legendary | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
797 | 720 | HoopaHoopa Confined | Psychic | Ghost | 80 | 110 | 60 | 150 | 130 | 70 | 6 | True |
798 | 720 | HoopaHoopa Unbound | Psychic | Dark | 80 | 160 | 60 | 170 | 130 | 80 | 6 | True |
799 | 721 | Volcanion | Fire | Water | 80 | 110 | 120 | 130 | 90 | 70 | 6 | True |
Secara default, method head() dan tail() akan mengembalikan 5 baris pertama/terakhir jika tidak diberikan suatu argumen.
shape
Memanggil attribute shape akan memberikan kita jumlah baris dan kolom dari suatu dataframe.
columns
Memanggil attribute columns akan memberikan kita index object berisi semua nama kolom dari suatu dataframe.
Index(['#', 'Name', 'Type 1', 'Type 2', 'HP', 'Attack', 'Defense', 'Sp. Atk',
'Sp. Def', 'Speed', 'Generation', 'Legendary'],
dtype='object')
index
Memanggil attribute columns akan memberikan kita index object berisi index baris suatu dataframe.
RangeIndex(start=0, stop=800, step=1)
Pandas dataframe memiliki banyak sekali methods dan attributes/properties. Untuk mempelajari lebih lanjut mengenai dataframe pandas, dokumentasi library pandas bisa diakses pada link berikut : Pandas essential basic functionality
Perhatikan pada atribut columns
dan index
yang telah dibahas sebelumnya, output kode adalah object index. Apa itu object index
? Dalam library Pandas, object index digunakan sebagai object yang menyimpan label suatu object lainnya.
Contoh : dalam object DataFrame, index object digunakan untuk menyimpan label baris (df.index
) dan kolom (df.columns
).
Index object juga memiliki beberapa attribute dan methods. Beberapa diantaranya :
Series indexing digunakan untuk mengambil value yang berkaitan dengan suatu index.
a 0.0
b 1.0
c 2.0
d 3.0
dtype: float64
Perhatikan, saat melakukan slicing dengan explicit index (misal, data['a':'c']
), final index diikutsertakan dalam outputnya (inklusif), sementara ketika melakukan slicing dengan implicit index (misal, data[0:2]
), final index tidak diikutsertakan dalam outputnya (tidak inklusif).
DataFrame indexing digunakan untuk mengambil 1 atau beberapa kolom dengan memanggil label/nama kolom yang bersesuaian.
0 Bulbasaur
1 Ivysaur
2 Venusaur
3 VenusaurMega Venusaur
4 Charmander
...
795 Diancie
796 DiancieMega Diancie
797 HoopaHoopa Confined
798 HoopaHoopa Unbound
799 Volcanion
Name: Name, Length: 800, dtype: object
Name | |
---|---|
0 | Bulbasaur |
1 | Ivysaur |
2 | Venusaur |
3 | VenusaurMega Venusaur |
4 | Charmander |
... | ... |
795 | Diancie |
796 | DiancieMega Diancie |
797 | HoopaHoopa Confined |
798 | HoopaHoopa Unbound |
799 | Volcanion |
800 rows × 1 columns
df['<column-name>']
akan mengembalikan kolom yang bersesuaian dalam bentuk Series.df[['<column-name>']]
akan mengembalikan kolom yang bersesuaian dalam bentuk dataframe.Name | HP | Defense | |
---|---|---|---|
0 | Bulbasaur | 45 | 49 |
1 | Ivysaur | 60 | 63 |
2 | Venusaur | 80 | 83 |
3 | VenusaurMega Venusaur | 80 | 123 |
4 | Charmander | 39 | 43 |
... | ... | ... | ... |
795 | Diancie | 50 | 150 |
796 | DiancieMega Diancie | 50 | 110 |
797 | HoopaHoopa Confined | 80 | 60 |
798 | HoopaHoopa Unbound | 80 | 60 |
799 | Volcanion | 80 | 120 |
800 rows × 3 columns
Kita bisa membuat suatu kolom baru dari kolom-kolom yang sudah ada. Misalkan kita buat suatu variabel bernama Total Attack
yang berisi hasil penjumlahan variabel Attack
dan Sp. Atk
Attack | Sp. Atk | Total Attack | |
---|---|---|---|
0 | 49 | 65 | 114 |
1 | 62 | 80 | 142 |
2 | 82 | 100 | 182 |
3 | 100 | 122 | 222 |
4 | 52 | 60 | 112 |
... | ... | ... | ... |
795 | 100 | 100 | 200 |
796 | 160 | 160 | 320 |
797 | 110 | 150 | 260 |
798 | 160 | 170 | 330 |
799 | 110 | 130 | 240 |
800 rows × 3 columns
Untuk indexing baris suatu dataframe, gunakan index baris
# | Name | Type 1 | Type 2 | HP | Attack | Defense | Sp. Atk | Sp. Def | Speed | Generation | Legendary | Total Attack | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | Bulbasaur | Grass | Poison | 45 | 49 | 49 | 65 | 65 | 45 | 1 | False | 114 |
1 | 2 | Ivysaur | Grass | Poison | 60 | 62 | 63 | 80 | 80 | 60 | 1 | False | 142 |
2 | 3 | Venusaur | Grass | Poison | 80 | 82 | 83 | 100 | 100 | 80 | 1 | False | 182 |
# | Name | Type 1 | Type 2 | HP | Attack | Defense | Sp. Atk | Sp. Def | Speed | Generation | Legendary | Total Attack | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | Bulbasaur | Grass | Poison | 45 | 49 | 49 | 65 | 65 | 45 | 1 | False | 114 |
2 | 3 | Venusaur | Grass | Poison | 80 | 82 | 83 | 100 | 100 | 80 | 1 | False | 182 |
4 | 4 | Charmander | Fire | NaN | 39 | 52 | 43 | 60 | 50 | 65 | 1 | False | 112 |
Untuk melakukan filtering pada suatu dataframe :
# | Name | Type 1 | Type 2 | HP | Attack | Defense | Sp. Atk | Sp. Def | Speed | Generation | Legendary | Total Attack | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
14 | 11 | Metapod | Bug | NaN | 50 | 20 | 55 | 25 | 25 | 30 | 1 | False | 45 |
32 | 27 | Sandshrew | Ground | NaN | 50 | 75 | 85 | 20 | 30 | 40 | 1 | False | 95 |
59 | 54 | Psyduck | Water | NaN | 50 | 52 | 48 | 65 | 50 | 55 | 1 | False | 117 |
75 | 69 | Bellsprout | Grass | Poison | 50 | 75 | 35 | 70 | 30 | 40 | 1 | False | 145 |
83 | 77 | Ponyta | Fire | NaN | 50 | 85 | 55 | 65 | 65 | 90 | 1 | False | 150 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
760 | 690 | Skrelp | Poison | Water | 50 | 60 | 60 | 60 | 60 | 30 | 6 | False | 120 |
762 | 692 | Clauncher | Water | NaN | 50 | 53 | 62 | 58 | 63 | 44 | 6 | False | 111 |
773 | 703 | Carbink | Rock | Fairy | 50 | 50 | 150 | 50 | 150 | 50 | 6 | False | 100 |
795 | 719 | Diancie | Rock | Fairy | 50 | 100 | 150 | 100 | 150 | 50 | 6 | True | 200 |
796 | 719 | DiancieMega Diancie | Rock | Fairy | 50 | 160 | 110 | 160 | 110 | 110 | 6 | True | 320 |
63 rows × 13 columns
# | Name | Type 1 | Type 2 | HP | Attack | Defense | Sp. Atk | Sp. Def | Speed | Generation | Legendary | Total Attack | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2 | Ivysaur | Grass | Poison | 60 | 62 | 63 | 80 | 80 | 60 | 1 | False | 142 |
2 | 3 | Venusaur | Grass | Poison | 80 | 82 | 83 | 100 | 100 | 80 | 1 | False | 182 |
3 | 3 | VenusaurMega Venusaur | Grass | Poison | 80 | 100 | 123 | 122 | 120 | 80 | 1 | False | 222 |
5 | 5 | Charmeleon | Fire | NaN | 58 | 64 | 58 | 80 | 65 | 80 | 1 | False | 144 |
6 | 6 | Charizard | Fire | Flying | 78 | 84 | 78 | 109 | 85 | 100 | 1 | False | 193 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
793 | 717 | Yveltal | Dark | Flying | 126 | 131 | 95 | 131 | 98 | 99 | 6 | True | 262 |
794 | 718 | Zygarde50% Forme | Dragon | Ground | 108 | 100 | 121 | 81 | 95 | 95 | 6 | True | 181 |
797 | 720 | HoopaHoopa Confined | Psychic | Ghost | 80 | 110 | 60 | 150 | 130 | 70 | 6 | True | 260 |
798 | 720 | HoopaHoopa Unbound | Psychic | Dark | 80 | 160 | 60 | 170 | 130 | 80 | 6 | True | 330 |
799 | 721 | Volcanion | Fire | Water | 80 | 110 | 120 | 130 | 90 | 70 | 6 | True | 240 |
589 rows × 13 columns
df[(df['HP'] > 100) & (df['Type 1'] == 'Fire')] # Mengambil data pada dataframe df yang memiliki nilai kolom `HP` > 100 dan `Type 1` == Fire
# | Name | Type 1 | Type 2 | HP | Attack | Defense | Sp. Atk | Sp. Def | Speed | Generation | Legendary | Total Attack | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
263 | 244 | Entei | Fire | NaN | 115 | 115 | 85 | 90 | 75 | 100 | 2 | True | 205 |
270 | 250 | Ho-oh | Fire | Flying | 106 | 130 | 90 | 110 | 154 | 90 | 2 | True | 240 |
559 | 500 | Emboar | Fire | Fighting | 110 | 123 | 65 | 100 | 65 | 65 | 5 | False | 223 |
615 | 555 | DarmanitanStandard Mode | Fire | NaN | 105 | 140 | 55 | 30 | 55 | 95 | 5 | False | 170 |
616 | 555 | DarmanitanZen Mode | Fire | Psychic | 105 | 30 | 105 | 140 | 105 | 55 | 5 | False | 170 |
df[(df['HP'] > 100) | (df['Type 1'] == 'Fire')] # Mengambil data pada dataframe df yang memiliki nilai kolom `HP` > 100 atau `Type 1` == Fire
# | Name | Type 1 | Type 2 | HP | Attack | Defense | Sp. Atk | Sp. Def | Speed | Generation | Legendary | Total Attack | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
4 | 4 | Charmander | Fire | NaN | 39 | 52 | 43 | 60 | 50 | 65 | 1 | False | 112 |
5 | 5 | Charmeleon | Fire | NaN | 58 | 64 | 58 | 80 | 65 | 80 | 1 | False | 144 |
6 | 6 | Charizard | Fire | Flying | 78 | 84 | 78 | 109 | 85 | 100 | 1 | False | 193 |
7 | 6 | CharizardMega Charizard X | Fire | Dragon | 78 | 130 | 111 | 130 | 85 | 100 | 1 | False | 260 |
8 | 6 | CharizardMega Charizard Y | Fire | Flying | 78 | 104 | 78 | 159 | 115 | 100 | 1 | False | 263 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
769 | 699 | Aurorus | Rock | Ice | 123 | 77 | 72 | 99 | 92 | 58 | 6 | False | 176 |
792 | 716 | Xerneas | Fairy | NaN | 126 | 131 | 95 | 131 | 98 | 99 | 6 | True | 262 |
793 | 717 | Yveltal | Dark | Flying | 126 | 131 | 95 | 131 | 98 | 99 | 6 | True | 262 |
794 | 718 | Zygarde50% Forme | Dragon | Ground | 108 | 100 | 121 | 81 | 95 | 95 | 6 | True | 181 |
799 | 721 | Volcanion | Fire | Water | 80 | 110 | 120 | 130 | 90 | 70 | 6 | True | 240 |
114 rows × 13 columns
Untuk filter yang lebih rumit, disarankan untuk mendefinisikan variabel condition
agar kode mudah terbaca.
Contoh : Filter (HP
>= 150) dan ((Type 1
== Water) atau (Legendary
== True))
condition = (df['HP'] >= 150) & ((df['Type 1'] == 'Water') | (df['Legendary'] == True))
df[condition]
# | Name | Type 1 | Type 2 | HP | Attack | Defense | Sp. Atk | Sp. Def | Speed | Generation | Legendary | Total Attack | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
351 | 321 | Wailord | Water | NaN | 170 | 90 | 45 | 90 | 45 | 60 | 3 | False | 180 |
544 | 487 | GiratinaAltered Forme | Ghost | Dragon | 150 | 100 | 120 | 100 | 120 | 90 | 4 | True | 200 |
545 | 487 | GiratinaOrigin Forme | Ghost | Dragon | 150 | 120 | 100 | 120 | 100 | 90 | 4 | True | 240 |
655 | 594 | Alomomola | Water | NaN | 165 | 75 | 80 | 40 | 45 | 65 | 5 | False | 115 |
Link Dataset : Data Penjualan Toko Baju Unikloh
Sebuah toko baju unikloh membutuhkan jasa seorang analis untuk menganalisis data penjualan baju yang mereka miliki. Sebelum itu, Pak Joko selaku pemilik toko ingin tahu beberapa hal mengenai data yang dia miliki. Berikut yang beliau minta :
price_per_unit
dan quantity
saja.total_price
, tapi sepertinya kolomnya hilang. Tolong buatkan kolomnya berdasarkan data yang ada.