country name indo version

This commit is contained in:
Debby
2026-06-07 08:09:14 +07:00
parent 512c08bff3
commit ca1e0d3949
3 changed files with 344 additions and 118 deletions
+72 -15
View File
@@ -10,7 +10,13 @@ Filtering Order:
5. Filter indicators with consistent presence across FIXED countries
6. Save analytical table (dengan nama/label lengkap untuk Looker Studio)
ADDED: Kolom indicator_name_id dan pillar_name_id (terjemahan Bahasa Indonesia)
ADDED:
- Kolom indicator_name_id dan pillar_name_id (terjemahan Bahasa Indonesia)
- Kolom country_name_id (terjemahan Bahasa Indonesia nama negara)
FIXED:
- Nama pilar "Access" -> "Akses" (konsisten di semua mapping)
- Nama negara ASEAN dalam Bahasa Indonesia
"""
import pandas as pd
@@ -40,21 +46,39 @@ from google.cloud import bigquery
# TRANSLATION DICTIONARIES
# =============================================================================
COUNTRY_NAME_ID_MAP: dict = {
# Nama resmi -> Bahasa Indonesia
"Brunei Darussalam" : "Brunei Darussalam",
"Cambodia" : "Kamboja",
"Indonesia" : "Indonesia",
"Lao People's Democratic Republic" : "Laos",
"Lao PDR" : "Laos",
"Malaysia" : "Malaysia",
"Myanmar" : "Myanmar",
"Philippines" : "Filipina",
"Singapore" : "Singapura",
"Thailand" : "Thailand",
"Timor-Leste" : "Timor-Leste",
"Viet Nam" : "Vietnam",
"Vietnam" : "Vietnam",
}
PILLAR_TRANSLATION_ID: dict = {
# 4 pilar utama Food Security
"Availability" : "Ketersediaan",
"Access" : "Keterjangkauan",
"Utilization" : "Pemanfaatan",
"Stability" : "Stabilitas",
"Sustainability": "Keberlanjutan",
# Variasi penulisan yang mungkin muncul
"availability" : "Ketersediaan",
"access" : "Keterjangkauan",
"utilization" : "Pemanfaatan",
"stability" : "Stabilitas",
"sustainability": "Keberlanjutan",
# 4 pilar utama Food Security — "Access" -> "Akses" (FIXED, bukan "Keterjangkauan")
"Availability" : "Ketersediaan",
"Access" : "Akses",
"Utilization" : "Pemanfaatan",
"Stability" : "Stabilitas",
"Sustainability" : "Keberlanjutan",
# Variasi penulisan huruf kecil
"availability" : "Ketersediaan",
"access" : "Akses",
"utilization" : "Pemanfaatan",
"stability" : "Stabilitas",
"sustainability" : "Keberlanjutan",
# Variasi dengan prefix "Food"
"Food Availability" : "Ketersediaan Pangan",
"Food Access" : "Keterjangkauan Pangan",
"Food Access" : "Akses Pangan",
"Food Utilization" : "Pemanfaatan Pangan",
"Food Stability" : "Stabilitas Pangan",
"Food Sustainability": "Keberlanjutan Pangan",
@@ -195,6 +219,13 @@ INDICATOR_TRANSLATION_ID: dict = {
}
def translate_country(name: str) -> str:
"""Terjemahkan nama negara ke Bahasa Indonesia. Fallback ke nama asli."""
if not name:
return name
return COUNTRY_NAME_ID_MAP.get(name.strip(), name)
def translate_indicator(name: str) -> str:
"""Terjemahkan nama indikator ke Bahasa Indonesia. Fallback ke nama asli."""
if not name:
@@ -226,6 +257,7 @@ class AnalyticalLayerLoader:
Output: fact_asean_food_security_selected -> DW layer (Gold) -> fs_asean_gold
Kolom tambahan:
- country_name_id : terjemahan Bahasa Indonesia dari country_name
- indicator_name_id : terjemahan Bahasa Indonesia dari indicator_name
- pillar_name_id : terjemahan Bahasa Indonesia dari pillar_name
"""
@@ -625,12 +657,24 @@ class AnalyticalLayerLoader:
# ------------------------------------------------------------------
# TAMBAHAN: kolom terjemahan Bahasa Indonesia
# country_name_id : terjemahan Bahasa Indonesia dari country_name [BARU]
# indicator_name_id : terjemahan Bahasa Indonesia dari indicator_name
# pillar_name_id : terjemahan Bahasa Indonesia dari pillar_name
# ------------------------------------------------------------------
analytical_df['country_name_id'] = analytical_df['country_name'].apply(translate_country)
analytical_df['indicator_name_id'] = analytical_df['indicator_name'].apply(translate_indicator)
analytical_df['pillar_name_id'] = analytical_df['pillar_name'].apply(translate_pillar)
# Log negara yang belum punya terjemahan
no_trans_ctr = analytical_df[
analytical_df['country_name_id'] == analytical_df['country_name']
]['country_name'].unique()
if len(no_trans_ctr) > 0:
self.logger.warning(
f" [TRANSLATION] {len(no_trans_ctr)} country/countries tidak ada di kamus "
f"(menggunakan nama asli): {list(no_trans_ctr)}"
)
# Log indikator yang belum punya terjemahan (fallback ke nama asli)
no_trans_ind = analytical_df[
analytical_df['indicator_name_id'] == analytical_df['indicator_name']
@@ -657,6 +701,7 @@ class AnalyticalLayerLoader:
# Pastikan tipe data konsisten
analytical_df['country_id'] = analytical_df['country_id'].astype(int)
analytical_df['country_name'] = analytical_df['country_name'].astype(str)
analytical_df['country_name_id'] = analytical_df['country_name_id'].astype(str)
analytical_df['indicator_id'] = analytical_df['indicator_id'].astype(int)
analytical_df['indicator_name'] = analytical_df['indicator_name'].astype(str)
analytical_df['indicator_name_id'] = analytical_df['indicator_name_id'].astype(str)
@@ -671,10 +716,21 @@ class AnalyticalLayerLoader:
self.logger.info(f" Kolom yang disimpan: {list(analytical_df.columns)}")
self.logger.info(f" Total rows: {len(analytical_df):,}")
# Log sample terjemahan negara
sample_ctr = (
analytical_df[['country_name', 'country_name_id']]
.drop_duplicates()
.sort_values('country_name')
)
self.logger.info("\n Terjemahan nama negara (EN -> ID):")
for _, r in sample_ctr.iterrows():
self.logger.info(f" {r['country_name']:<35} -> {r['country_name_id']}")
# Schema BigQuery
schema = [
bigquery.SchemaField("country_id", "INTEGER", mode="REQUIRED"),
bigquery.SchemaField("country_name", "STRING", mode="REQUIRED"),
bigquery.SchemaField("country_name_id", "STRING", mode="REQUIRED"),
bigquery.SchemaField("indicator_id", "INTEGER", mode="REQUIRED"),
bigquery.SchemaField("indicator_name", "STRING", mode="REQUIRED"),
bigquery.SchemaField("indicator_name_id", "STRING", mode="REQUIRED"),
@@ -710,7 +766,8 @@ class AnalyticalLayerLoader:
'fixed_countries': len(self.selected_country_ids),
'no_gaps' : True,
'layer' : 'gold',
'columns' : 'id + name + name_id (Looker Studio ready)'
'columns' : 'id + name + name_id (Looker Studio ready)',
'added_columns' : ['country_name_id', 'indicator_name_id', 'pillar_name_id'],
}),
'validation_metrics' : json.dumps({
'fixed_countries' : len(self.selected_country_ids),