dersblog

Ticaret Veri Tabanı, Önişlemler, Raporlar

200 ülke için ikili ticaret ilişkilerinin verisi B.A.C.I. tabanında paylaşılıyor [1]. Bu yazıda tabanın 2022 yılı için olan verisini işleyeceğiz, veri 5000 ürün kategorisini içermekte, kategori sistemi "harmonize edilmiş sistem" adı verilen 6 sayılık bir kod kullanıyor. BACI kayıtları alan / satan bilgini içerir, yani her ülke ikilisi için ihraç edici / ithal edici kayıtlanmıştır, ve bu ilişkide her ürünün ihraç/ithal miktarı ve değeri de tabanda vardır. Taban tek bir csv dosyası, kolonlar,

t: yıl
i: ihraççı
j: ithalcı
k: ürün
v: değer
q: miktar

Para deger birimi 1000 Amerikan doları, miktar ise metrik ton.

Girdi verisine bir göz atalım,

baci_dir = "/opt/Downloads/baci"

!head -10 $baci_dir/BACI_HS22_Y2022_V202401b.csv
t,i,j,k,v,q
2022,4,20,210610,        0.357,        0.002
2022,4,20,210690,        0.061,        0.001
2022,4,20,271000,        5.807,        8.103
2022,4,20,843131,        0.313,        0.022
2022,4,31,080211,        2.027,        0.500
2022,4,31,081310,        0.912,        0.240
2022,4,31,252620,        5.642,       47.550
2022,4,31,340600,        0.167,        0.002
2022,4,31,680221,        5.034,       21.000

Kayıtları işlemek için [2]'deki paralel, satırsal işleyici altyapısını kullanacağız. CSV dosyasında her satırda ihraç eden ülke / ithal eden ülke / ürün üçlüsü var. Alttaki kod her satırı okurken iki ülke arasındaki değeri en yüksek ürünü takip ediyor. Bu takip basit bir Python sözlüğü ile yapılıyor, sözlükteki anahtar iki kimliğin birleşimi, ihraççı - ithalci ile bir özgün, birleşik kimlik yaratılıyor, bu kimliğin değeri o iki ülke arasındaki o ana kadar kayıtlarda görülen en yüksek değeri taşıyor, eğer yeni satırda daha yüksek değer bulunursa sözlük güncelleniyor. Diğer bir sözlükte bu ikili için o değerin tekabul ettiği ürünün anahtarı kayıt ediliyor.

from timeit import default_timer as timer
from multiprocessing import Process
from datetime import timedelta
import util, json, os

class BaciJob:
    def __init__(self):
        self.infile = "" 
        self.chunk = -1 
        self.P = {}
        self.V = {}
        self.header = {'t':0,'i':1,'j':2,'k':3,'v':4,'q':5}
    def exec(self,line):        
        tok = line.strip().replace(' ','').split(',')
        i,j = tok[self.header['i']], tok[self.header['j']]
        i,j = int(i),int(j)
        v = float(tok[self.header['v']])
        q = tok[self.header['q']]
        prod = tok[self.header['k']]
        key = "%d-%d" % (i,j)
        if key not in self.V or v > self.V[key]:
            self.V[key] = v
            self.P[key] = prod

    def post(self):
        print (self.infile)
        fout = open(baci_dir + "/out-p.json","w")
        fout.write(json.dumps(self.P))
        fout.close()

        fout = open(baci_dir + "/out-v.json","w")
        fout.write(json.dumps(self.V))
        fout.close()

def process_baci_top_products():
    file_name = baci_dir + "/BACI_HS22_Y2022_V202401b.csv"
    start = timer()
    N = 1 
    ps = [Process(target=util.process,args=(file_name, i, N, BaciJob(),1)) for i in range(N)]
    for p in ps: p.start()
    for p in ps: p.join()
    end = timer()
    print('elapsed time', timedelta(seconds=end-start))
process_baci_top_products()
elapsed time 0:01:41.059329

İşlem bitince sonuçlar baci_dir dizini altında yazılmış olmalı. Referans edilen process kodu util.py içinde.

Çıktıları raporlamak için yeni iki fonksiyon yazalım, bu fonksiyonlardan baci_top_product() verili iki ülke için, ihraccı / ithalci olarak, en değerli ürün kategorisini ve o kategorinin tanmını geri getirsin. Bu bilgilerin raporlanabilmesi için bazı referans csv dosyaları okunmalı, ardı ardı yapılacak fonksiyon çağrılarında sürekli okunmasın diye onları otomatik olarak önbellege gönderiyoruz, @lru_cache kullanımına dikkat, init() ilk çağrıldığında dört tane veri objesini diskten okuyup geri döndürür, sonraki çağrılarda önbellekteki objeler diske gitmeden geri verilir.

from functools import lru_cache
import pandas as pd, json, textwrap

@lru_cache(maxsize=1) # returned types are cached
def init():
   baci_cc = pd.read_csv(baci_dir + '/country_codes_V202401b.csv',index_col='country_name')
   baci_pc = pd.read_csv(baci_dir + '/product_codes_HS22_V202401b.csv',index_col='code')
   baci_p = json.loads(open(baci_dir + "/out-p.json").read())
   baci_v = json.loads(open(baci_dir + "/out-v.json").read())
   return baci_cc, baci_pc, baci_p, baci_v

def baci_top_product(frc, toc):
    baci_cc, baci_pc, baci_p, baci_v = init()
    key = "%d-%d" % (baci_cc.loc[frc].country_code, baci_cc.loc[toc].country_code)
    print('$', f"{baci_v[key]*1000:,}")
    s = baci_pc.loc[int(baci_p[key])].description
    for x in textwrap.wrap(s, width=70):
        print (x)

Çin'in Fransa'ya ihraç ettiği en çok para getiren ürünü nedir?

baci_top_product("China","France")
$ 979,185,844.0
Communication apparatus (excluding telephone sets or base stations):
machines for the reception, conversion and transmission or
regeneration of voice, images or other data, including switching and
routing apparatus

Rusya ve Hindistan,

baci_top_product("Russian Federation","India")
$ 25,534,776,517.0
Oils: petroleum oils and oils obtained from bituminous minerals, crude

Kaynaklar

[1] BACI

[2] Bayramlı, Paralel, Satır Bazlı Dosya İşlemek


Yukarı