Cara Membuat Peta Heatmap Menggunakan Geopandas di Python#
Geopandas adalah salah satu library Python yang digunakan untuk membuat peta. Basis penggunaan Geopandas adalah dataframe, sama seperti penggunaan library Pandas. Sebelum menginstall Geopandas, pastikan ketiga library berikut sudah terinstall dengan baik.
Lalu, Geopanda bisa diinstall dengan perintah
pip install geopandas
Jika semua sudah diinstall. Kita lanjut ke tahap membuat peta heatmap.
Untuk membuat peta heatmap pada tutorial ini, dibutuhkan file SHP batas administrasi wilayah. Pada tutorial ini, kita menggunakan batas administrasi provinsi di Indonesia. Data yang akan disajikan berupa jumlah mahasiswa di perguruan tinggi negeri dan swasta pada tahun 2024. Data diperoleh dari BPS.
[1]:
import geopandas as gpd
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
import pandas as pd
c:\Users\auliatdmrc\AppData\Local\Programs\Python\Python38\lib\site-packages\geopandas\_compat.py:124: UserWarning: The Shapely GEOS version (3.8.1-CAPI-1.13.3) is incompatible with the GEOS version PyGEOS was compiled with (3.10.4-CAPI-1.16.2). Conversions between both will be slow.
warnings.warn(
[20]:
# File SHP
file_shp = "D:\SHP\BATAS_PROVINSI_RBI\BATAS_PROVINSI_RBI.shp"
# File Data
file_data = "D:\code\PYTHON\Geopandas_Tutorial\Data\Jumlah_Mahasiswa_PTN_PTS_2024.xlsx"
[21]:
df_shapefile = gpd.read_file(file_shp)
df_shapefile.head()
[21]:
| OBJECTID | NAMOBJ | FCODE | REMARK | METADATA | SRS_ID | KDBBPS | KDCBPS | KDCPUM | KDEBPS | ... | WADMKK | WADMPR | WIADKC | WIADKK | WIADPR | WIADKD | SHAPE_Leng | SHAPE_Area | KDPKAB_2 | geometry | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 498.0 | Deiyai | BA03050040 | NaN | TASWIL5000020230907KABKOTA | 4326 | NaN | NaN | NaN | NaN | ... | Deiyai | Papua Tengah | NaN | Paniai | Papua | 0.0 | 3.392139 | 0.231851 | 9408.0 | MULTIPOLYGON Z (((134.83115 -3.12258 0.00000, ... |
| 1 | 7.0 | Bolaang Mongondow | BA03050040 | NaN | TASWIL5000020230907KABKOTA | 4326 | NaN | NaN | NaN | NaN | ... | Bolaang Mongondow | Sulawesi Utara | NaN | NaN | NaN | 0.0 | 3.657437 | 0.267425 | 7101.0 | MULTIPOLYGON Z (((124.35299 0.41822 0.00000, 1... |
| 2 | 508.0 | Kota Sorong | BA03050040 | NaN | TASWIL5000020230907KABKOTA | 4326 | NaN | NaN | NaN | NaN | ... | Kota Sorong | Papua Barat Daya | NaN | Sorong | Papua Barat | 0.0 | 1.229888 | 0.016677 | 9671.0 | MULTIPOLYGON Z (((129.72236 -1.86574 0.00000, ... |
| 3 | 496.0 | Biak Numfor | BA03050040 | NaN | TASWIL5000020230907KABKOTA | 4326 | NaN | NaN | NaN | NaN | ... | Biak Numfor | Papua | NaN | NaN | NaN | 0.0 | 5.355326 | 0.183452 | 9106.0 | MULTIPOLYGON Z (((135.01582 -1.48624 0.00000, ... |
| 4 | 495.0 | Asmat | BA03050040 | NaN | TASWIL5000020230907KABKOTA | 4326 | NaN | NaN | NaN | NaN | ... | Asmat | Papua Selatan | NaN | Merauke | Papua | 0.0 | 10.505102 | 2.041032 | 9304.0 | MULTIPOLYGON Z (((138.49926 -8.32289 0.00000, ... |
5 rows × 28 columns
[22]:
# Reading data
df_data = pd.read_excel(file_data)
df_data.head()
[22]:
| Provinsi | jumlah_mahasiswa_negeri_swasta | |
|---|---|---|
| 0 | Aceh | 151574 |
| 1 | Sumatera Utara | 404298 |
| 2 | Sumatera Barat | 195540 |
| 3 | Riau | 152254 |
| 4 | Jambi | 67625 |
Pada file SHP, nama provinsi berada pada kolom WADMPR, sedangkan pada file data, nama kolom provinsi dinamakan sebagai Provinsi. Maka, pada file data, nama kolom perlu diubah menjadi WADMPR. Perubahan ini bertujuan agar kedua data bisa digabung (merge) dengan menggunakan key yang sama, yaitu WADMPR.
[23]:
df_data.rename(columns={'Provinsi' : 'WADMPR'}, inplace=True)
df_data.head()
[23]:
| WADMPR | jumlah_mahasiswa_negeri_swasta | |
|---|---|---|
| 0 | Aceh | 151574 |
| 1 | Sumatera Utara | 404298 |
| 2 | Sumatera Barat | 195540 |
| 3 | Riau | 152254 |
| 4 | Jambi | 67625 |
[24]:
df_shapefile_merged = df_shapefile.merge(df_data, on='WADMPR', how='left')
df_shapefile_merged.info()
<class 'geopandas.geodataframe.GeoDataFrame'>
RangeIndex: 39 entries, 0 to 38
Data columns (total 29 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 OBJECTID 39 non-null float64
1 NAMOBJ 39 non-null object
2 FCODE 39 non-null object
3 REMARK 0 non-null float64
4 METADATA 39 non-null object
5 SRS_ID 39 non-null object
6 KDBBPS 0 non-null float64
7 KDCBPS 0 non-null float64
8 KDCPUM 0 non-null float64
9 KDEBPS 0 non-null float64
10 KDEPUM 0 non-null float64
11 KDPBPS 0 non-null float64
12 KDPKAB 38 non-null object
13 KDPPUM 38 non-null object
14 LUASWH 39 non-null float64
15 TIPADM 39 non-null int64
16 WADMKC 0 non-null float64
17 WADMKD 0 non-null float64
18 WADMKK 38 non-null object
19 WADMPR 38 non-null object
20 WIADKC 0 non-null float64
21 WIADKK 11 non-null object
22 WIADPR 10 non-null object
23 WIADKD 34 non-null float64
24 SHAPE_Leng 39 non-null float64
25 SHAPE_Area 39 non-null float64
26 KDPKAB_2 38 non-null float64
27 geometry 39 non-null geometry
28 jumlah_mahasiswa_negeri_swasta 38 non-null float64
dtypes: float64(17), geometry(1), int64(1), object(10)
memory usage: 9.0+ KB
Kemudian, kita akan membuat heatmap dengan menggunakan variabel jumlah_mahasiswa_negeri_swasta dari df_shapefile_merged dengan menggunakan script sebagai berikut
[30]:
plt.rcParams['font.family'] = "Serif"
plt.rcParams.update({'font.size': 14})
fig, ax = plt.subplots(figsize=(15,8))
df_shapefile_merged.plot(
ax=ax,
column='jumlah_mahasiswa_negeri_swasta',
cmap='YlOrRd',
legend=True,
scheme='equal_interval',
k=10,
)
df_shapefile_merged.boundary.plot(ax=ax, color='k', linewidth=0.5)
ax.set_title('Jumlah Mahasiswa Perguruan Tinggi Negeri dan Swasta\ndi Bawah Kementerian Pendidikan Tinggi, Sains, dan Teknologi Tahun 2024')
ax.yaxis.set_minor_locator(MultipleLocator(1))
ax.xaxis.set_minor_locator(MultipleLocator(1))
Keterangan legend di atas dihasilkan berdasarkan rentang equal_interval sebanyak 10 bagian (k=10). Namun, tampilan heatmap di atas terlihat terganggu oleh letak legend yang menimpa tampilan utama heatmap. Maka, perlu penyesuaian ukuran font legend dengan menambah atribut fontsize pada fungsi plot (baris 13). Kita atur ukuran font sebesar 8.
[34]:
plt.rcParams['font.family'] = "Serif"
plt.rcParams.update({'font.size': 14})
fig, ax = plt.subplots(figsize=(15,8))
df_shapefile_merged.plot(
ax=ax,
column='jumlah_mahasiswa_negeri_swasta',
cmap='YlOrRd',
legend=True,
scheme='equal_interval',
k=10,
legend_kwds={"loc": "center left", "fontsize":8}
)
df_shapefile_merged.boundary.plot(ax=ax, color='k', linewidth=0.5)
ax.set_title('Jumlah Mahasiswa Perguruan Tinggi Negeri dan Swasta\ndi Bawah Kementerian Pendidikan Tinggi, Sains, dan Teknologi Tahun 2024')
ax.yaxis.set_minor_locator(MultipleLocator(1))
ax.xaxis.set_minor_locator(MultipleLocator(1))
Tampilan legend masih sedikit menimpa tampilan utama heatmap, maka posisi legend perlu disesuaikan dengan menambahkan script seperti pada baris ke 6 (x_legend_pos, y_legend_pos = 0.01, 0.2) untuk mendefinisikan posisi legend. Kemudian penambahan atribut bbox_to_anchor pada legend_kwds pada baris ke 15. Script pembaharuannya adalah sebagai berikut.
[38]:
plt.rcParams['font.family'] = "Serif"
plt.rcParams.update({'font.size': 14})
fig, ax = plt.subplots(figsize=(15,8))
x_legend_pos, y_legend_pos = 0.01, 0.2
df_shapefile_merged.plot(
ax=ax,
column='jumlah_mahasiswa_negeri_swasta',
cmap='YlOrRd',
legend=True,
scheme='equal_interval',
k=10,
legend_kwds={"loc": "center left", "fontsize":8, "bbox_to_anchor": (x_legend_pos, y_legend_pos)}
)
df_shapefile_merged.boundary.plot(ax=ax, color='k', linewidth=0.5)
ax.set_title('Jumlah Mahasiswa Perguruan Tinggi Negeri dan Swasta\ndi Bawah Kementerian Pendidikan Tinggi, Sains, dan Teknologi Tahun 2024')
ax.yaxis.set_minor_locator(MultipleLocator(1))
ax.xaxis.set_minor_locator(MultipleLocator(1))
x_legend_pos dan y_legend_pos bisa disesuaikan dengan kebutuhan untuk mengatur letak legend. Nilai x yang bertambah, maka posisi legend akan bergeser ke kanan dan nilai y bertambah, maka posisi legend akan naik ke atas. Kemudian, kita bisa menambahkan judul legend pada atribut legend_kdws dengan keterangan title: dengan ukurannya, title_fontsize di atur sebesar 8 seperti pada baris ke 15 berikut
[45]:
plt.rcParams['font.family'] = "Serif"
plt.rcParams.update({'font.size': 14})
fig, ax = plt.subplots(figsize=(15,8))
x_legend_pos, y_legend_pos = 0.005, 0.21
df_shapefile_merged.plot(
ax=ax,
column='jumlah_mahasiswa_negeri_swasta',
cmap='YlOrRd',
legend=True,
scheme='equal_interval',
k=10,
legend_kwds={"loc": "center left", "fontsize":8, "bbox_to_anchor": (x_legend_pos, y_legend_pos), "title":"Jumlah Mahasiswa", "title_fontsize":8,}
)
df_shapefile_merged.boundary.plot(ax=ax, color='k', linewidth=0.5)
ax.set_title('Jumlah Mahasiswa Perguruan Tinggi Negeri dan Swasta\ndi Bawah Kementerian Pendidikan Tinggi, Sains, dan Teknologi Tahun 2024')
ax.yaxis.set_minor_locator(MultipleLocator(1))
ax.xaxis.set_minor_locator(MultipleLocator(1))
Jika kita lihat lebih lanjut, tampilan rentang pada legend dipisahkan oleh tanda koma. Agar lebih sesuai, kita bisa modifikasi pemisahannya dengan tanda “-”. Modifikasi ini dilakukan dengan menambah script seperti pada baris 18-23 sebagai berikut.
[46]:
plt.rcParams['font.family'] = "Serif"
plt.rcParams.update({'font.size': 14})
fig, ax = plt.subplots(figsize=(15,8))
x_legend_pos, y_legend_pos = 0.005, 0.21
df_shapefile_merged.plot(
ax=ax,
column='jumlah_mahasiswa_negeri_swasta',
cmap='YlOrRd',
legend=True,
scheme='equal_interval',
k=10,
legend_kwds={"loc": "center left", "fontsize":8, "bbox_to_anchor": (x_legend_pos, y_legend_pos), "title":"Jumlah Mahasiswa", "title_fontsize":8,}
)
legend = ax.get_legend()
# Iterate through the legend text items and replace the commas
for text in legend.get_texts():
current_label = text.get_text()
new_label = current_label.replace(',', ' -') # Replace ' , ' with ' - '
text.set_text(new_label)
df_shapefile_merged.boundary.plot(ax=ax, color='k', linewidth=0.5)
ax.set_title('Jumlah Mahasiswa Perguruan Tinggi Negeri dan Swasta\ndi Bawah Kementerian Pendidikan Tinggi, Sains, dan Teknologi Tahun 2024')
ax.yaxis.set_minor_locator(MultipleLocator(1))
ax.xaxis.set_minor_locator(MultipleLocator(1))