AFAD verisini kendi sunucumda ayrıştırırken öğrendiklerim

这篇内容暂时只有 Türkçe 版本,以下是原文。

Geçen ay AFAD’ın açık deprem kataloğunu kendi makineme çekip aylık bir özet çıkarmayı denedim. Amaç büyüktü: son 12 ayın M≥3.0 kayıtlarını il bazında saymak. Veri JSON olarak geliyor, ben de Python ile işledim. İlk denemede 38 bin kaydın içinden sadece 200 tanesini doğru ile eşleştirebildim; geri kalanı ya boş ya da yanlış ildi. Sorun veride değil, benim varsayımımdaydı.

Önce ham kaydın nasıl geldiğine bakmak gerekti. Benim kullandığım sürümde her kayıt şöyle:

# afad_parse.py
import json, re

with open("depremler.json", encoding="utf-8") as f:
    ham = json.load(f)

print(json.dumps(ham[0], ensure_ascii=False, indent=2)[:400])

Çıktıda yer alanı “İzmir (Karaburun) açıkları” gibi serbest metin. Ben bunu split(" ")[0] ile ayırmaya kalktım; “İzmir” çalıştı, “Karaburun” tek başına geldiğinde patladı. “Manisa (Akhisar)” ise bambaşka bir şey verdi. Katalogda il adı her zaman başta değil; bazı kayıtlarda “X ilçesi (Y ilçesi)” sırası değişiyor, bazılarında hiç il yok.

İkinci denemede 81 il adını ayrı bir listeye alıp yer metninde geçen ilk eşleşmeyi aradım:

iller = ["Adana", "Adıyaman", ...]  # 81 il

def il_bul(yer: str):
    if not yer:
        return None
    for il in iller:
        if il.lower() in yer.lower():
            return il
    return None

Bu sefer 38 binin 36 bini eşleşti, ama “Kars” ile “Kars” arasındaki fark yüzünden yanlış eşleşmeler çıktı: “Kars” kelimesi “Karslılar” gibi bir ilçe adında da geçebiliyor. Türkçe lower() de “İ” harfinde sorun çıkarıyor; “İzmir”.lower() bende “i̇zmir” gibi noktalı bir karakter üretti ve in kontrolü tutmadı. Bunu casefold() ile düzeltmedim, çünkü Türkçe’de doğru davranış için ayarı ayrıca yapmak gerekiyor; ben de kısa yoldan yer.replace("İ", "i").replace("I", "ı").lower() ile geçtim. Bu bile “Iğdır” ile “ığdır” arasında hâlâ sınırda.

Asıl mesele şu: il adlarını serbest metinden çıkarmak kırılgan bir iş. Katalogda ayrı bir il alanı yoksa, en sağlam yol il adlarını baştan bir sözlükte tutup metni normalize etmek ve yalnızca tam kelime eşleşmesi aramak. Ama o zaman da “açıkları” gibi ekler yüzünden kayıt kaybediyorsunuz. Ben iki yöntemi birleştirdim: önce tam kelime, olmazsa ilk eşleşme, o da olmazsa None. Sonuçta 38 binin 35 bini tuttu, 3 bini belirsiz kaldı. Bunları ayrı bir dosyaya yazdım; onları elle kontrol etmek iki saatimi aldı.

Beklediğimden farklı çıkan şey şu oldu: veri setindeki en büyük sorun eksik il değil, aynı depremin birden fazla kayıtta farklı yer metinleriyle görünmesi. Revizyon kayıtları ayrı satır olarak geliyor ve aynı olayı iki kez sayabiliyorsunuz. Ben olay kimliği (eventID) üzerinden tekilleştirdim; bu alan yoksa tarih-saat ve koordinat yuvarlamasıyla eşleştirdim. Tekilleştirmeden önce aylık sayı 4.100 çıkıyordu, sonra 3.600’e indi. Aradaki fark tamamen mükerrer kayıtlardı.

Nerede kırılıyor: yeni bir il adı eklendiğinde (mesela büyükşehir sınırı değişince) listeyi güncellemeyi unutursanız sessizce kaybediyorsunuz. Ben bunu fark etmedim bile; ancak aylık toplam bir önceki aya göre yüzde 20 düşünce şüphelendim. Bir de koordinat bazlı eşleştirme yaparsanız, il sınırına çok yakın depremler iki ile birden düşebiliyor. Ben en yakın il merkezini almayı denedim, sahil açıklarındaki depremler yanlış ile gitti.

Şimdi aynı işi yapacak biri için tek tavsiyem: ham veriyi asla doğrudan saymayın, önce tekilleştirin, sonra il eşleştirmesini ayrı bir adımda yapın ve belirsiz kalanları ayrı tutun. Sizin kataloğunuzda il alanı var mı, yoksa siz de bu metin ayrıştırma işiyle mi uğraşıyorsunuz?

0
赞同度 100% · 0 条评论 · 5 阅读

0 条评论

支持 Markdown · 回复会实时推送给对方

还没有评论,写下第一条。