Logistics Problem lΓ challenge thα»© x cα»§a Shopee Code League 2020 – mα»t cuα»c thi vα» Code vΓ Data kΓ©o dΓ i 2 thΓ‘ng vα»i cΓ‘c challenge khΓ‘c nhau. BΓ i toΓ‘n Data Analytics lαΊ§n nΓ y tiαΊΏp tα»₯c lΓ mα»t chα»§ Δα» vα» Logistics – hay nΓ³i nΓ΄m na lΓ βship hΓ ngβ. Nhiα»m vα»₯ cα»§a cΓ‘c Δα»i lΓ xΓ‘c Δα»nh cΓ‘c ΔΖ‘n hΓ ng giao trα» hαΊΉn dα»±a trΓͺn data vΓ bα» rule cho sαΊ΅n. Sau mα»t khoαΊ£ng thα»i gian tΓ¬m hiα»u vΓ implement thΓ¬ mΓ¬nh xin giα»i thiα»u ΔαΊΏn cΓ‘c bαΊ‘n giαΊ£i phΓ‘p cα»§a team (score: 1.0/1.0).
Δα» bΓ i vΓ mΓ΄ tαΊ£ dα»― liα»u trΓͺn Kaggle: [Open] Shopee Code League – Logistics
Dα»― liα»u Δược public trΓͺn Kaggle
Dα»― liα»u cΓ³ 3.176.313 dΓ²ng x 6 cα»t:
- orderid: MΓ£ ΔΖ‘n hΓ ng, duy nhαΊ₯t trΓͺn toΓ n bα» dα»― liα»u.
- pick: Thα»i gian lαΊ₯y hΓ ng dΖ°α»i dαΊ‘ng epoch timestamp seconds.
- 1st_deliver_attempt: Thα»i gian giao hΓ ng lαΊ§n 1 dΖ°α»i dαΊ‘ng epoch timestamp seconds.
- 2nd_deliver_attempt: Thα»i gian giao hΓ ng lαΊ§n 2 dΖ°α»i dαΊ‘ng epoch timestamp seconds. NαΊΏu 1 ΔΖ‘n hΓ ng Δược giao thΓ nh cΓ΄ng trong lαΊ§n ΔαΊ§u thΓ¬ sαΊ½ khΓ΄ng cΓ³ lαΊ§n giao thα»© 2.
- buyeraddress: Δα»a Δiα»m ngΖ°α»i mua (Δα»a Δiα»m ΔΓch).
- selleraddress: Δα»a Δiα»m ngΖ°α»i bΓ‘n (Δα»a Δiα»m gα»c).
Mα»t dΓ²ng dα»― liα»u thα» hiα»n cho mα»t ΔΖ‘n hΓ ng trΓͺn nα»n tαΊ£ng Shopee.
YΓͺu cαΊ§u cα»§a bΓ i toΓ‘n lαΊ§n nΓ y khΓ‘ ΔΖ‘n giαΊ£n: XΓ‘c Δα»nh cΓ‘c ΔΖ‘n hΓ ng giao trα» dα»±a trΓͺn Service Level Agreements (SLA).
SLA mΓ΄ tαΊ£ khoαΊ£ng thα»i gian giao hΓ ng cam kαΊΏt cα»§a mα»t Δα»i tΓ‘c giao hΓ ng giα»―a 2 Δα»a Δiα»m vΓ Δược Δα»nh nghΔ©a dΖ°α»i ΔΓ’y:
Ma trαΊn SLA giα»―a cΓ‘c Δα»a Δiα»m
Thα»i gian giao hΓ ng bαΊ―t ΔαΊ§u tΓnh tα»« ngΓ y tiαΊΏp theo sau ngΓ y lαΊ₯y hΓ ng (pick up date) ΔαΊΏn lαΊ§n giao hΓ ng thα»© nhαΊ₯t. NαΊΏu lαΊ§n ΔαΊ§u giao hΓ ng khΓ΄ng thΓ nh cΓ΄ng thΓ¬ lαΊ§n giao hΓ ng thα»© hai khΓ΄ng Δược lα»n hΖ‘n 3 ngΓ y tα»« lαΊ§n giao thα»© nhαΊ₯t, bαΊ₯t kα» lα» trΓ¬nh.
Thα»i gian giao hΓ ng chα» tΓnh tα»« Thα»© Hai ΔαΊΏn Thα»© BαΊ£y vΓ loαΊ‘i trα»« 4 ngΓ y lα» :
- 2020-03-08
- 2020-03-25
- 2020-03-30
- 2020-03-31
LΖ°u Γ½: cαΊ§n chuyα»n epoch timestamp sang GMT+8 trΖ°α»c khi tΓnh toΓ‘n.
NhΖ° vαΊy ta cΓ³ cΓ‘c rule sau Δα» xΓ‘c Δα»nh ΔΖ‘n hΓ ng trα» :
-
Thα»i gian tα»« lΓΊc lαΊ₯y hΓ ng ΔαΊΏn lΓΊc giao lαΊ§n 1 lα»n hΖ‘n thα»i gian cam kαΊΏt SLA giα»―a 2 Δα»a Δiα»m ngΖ°α»i bΓ‘n vΓ ngΖ°α»i mua.
-
HoαΊ·c nαΊΏu cΓ³ giao lαΊ§n thα»© hai thΓ¬ thα»i gian giao hΓ ng tα»« lαΊ§n giao thα»© nhαΊ₯t tα»i lαΊ§n giao thα»© hai lα»n hΖ‘n 3 ngΓ y.
Load dα»― liα»u vΓ xem nhα»―ng thuα»c tΓnh cα»§a dα»― liα»u:
data_path = "./data/delivery_orders_march.csv"
result_path = "./data/result.csv"
d = pd.read_csv(data_path)
SΖ‘ lược vα» dα»― liα»u
Fix nhα»―ng giΓ‘ trα» bα» miss.
d['1st_deliver_attempt'] = d['1st_deliver_attempt'].astype(np.int64)
d['2nd_deliver_attempt'] = d['2nd_deliver_attempt'].fillna(0).astype(np.int64)
Khα»i tαΊ‘o cΓ‘c Δα»a Δiα»m vΓ mαΊ£ng SLA phα»₯c vα»₯ tΓnh toΓ‘n SLA.
holidays = [ "2020-03-08", "2020-03-25", "2020-03-30", "2020-03-31" ]
places = [ "metro manila", "luzon", "visayas", "mindanao" ]
# mapping for city index
places_map = { place:i for i, place in enumerate(places)}
# sla_map[seller][buyer]
sla_map = [[3, 5, 7, 7],
[5, 5, 7, 7],
[7, 7, 7, 7],
[7, 7, 7, 7]]
XΓ‘c Δα»nh Δα»a Δiα»m ngΖ°α»i bΓ‘n vΓ ngΖ°α»i mua, giαΊ£i quyαΊΏt trΖ°α»ng hợp trΓΉng tΓͺn Δα»a Δiα»m nhΖ°ng α» nhα»―ng vα» trΓ khΓ‘c nhau. Sau ΔΓ³ thay thαΊΏ Δα»a chα» bαΊ±ng index cα»§a Δα»a Δiα»m trong SLA map.
# convert address to city index
def get_place_index(address):
return np.argmax([address.lower().rfind(i) for i in places])
d["buyeraddress"] = d["buyeraddress"].apply(lambda x: get_place_index(x))
d["selleraddress"] = d["selleraddress"].apply(lambda x: get_place_index(x))
TΓnh toΓ‘n SLA cho toΓ n bα» dα»― liα»u.
d["sla"] = d.apply(lambda x: sla_map[x["selleraddress"]][x["buyeraddress"]], axis=1)
Chuyα»n timestamp α» cΓ‘c cα»t ngΓ y thΓ nh GMT+8 vΓ bα» Δi phαΊ§n time.
dt_columns = ['pick', '1st_deliver_attempt', '2nd_deliver_attempt']
for dt_col in dt_columns:
d[dt_col] = (d[dt_col] + 3600*8) // (3600*24)
TΓnh toΓ‘n ngΓ y giao hΓ ng dΓΉng hΓ m busday_count cα»§a NumPy.
t1 = d['pick'].values.astype('datetime64[D]')
t2 = d['1st_deliver_attempt'].values.astype('datetime64[D]')
t3 = d['2nd_deliver_attempt'].values.astype('datetime64[D]')
d['num_days1'] = np.busday_count(t1, t2, weekmask="1111110", holidays=holidays)
d['num_days2'] = np.busday_count(t2, t3, weekmask="1111110", holidays=holidays)
Cuα»i cΓΉng lΓ xΓ‘c Δα»nh ΔΖ‘n hΓ ng giao trα» dα»±a trΓͺn cΓ‘c rule ΔΓ£ xΓ‘c Δα»nh.
d['is_late'] = (d['num_days1'] > d['sla']) | (d['num_days2'] > 3)
d['is_late'] = d['is_late'].astype(int)
Ghi file vΓ nα»p.
result = d[["orderid", "is_late"]]
result.to_csv(result_path, index=False)
BΓ³c thα» nhα»―ng thαΊ±ng trα» ra xem nΓ³ nhΖ° thαΊΏ nΓ o π
Nhα»―ng ΔΖ‘n hΓ ng giao trα»
Sau khi chαΊ‘y xα» lΓ½ xong thΓ¬ phΓ‘t hiα»n cΓ³ 762.422 ΔΖ‘n hΓ ng giao trα» π
CΓ‘c bαΊ‘n cΓ³ thα» xem toΓ n bα» notebook, dα»― liα»u tαΊ‘i GitHub: logistics-shopee-code-league
So vα»i challenge trΖ°α»c (Order Burshing Problem), challenge lαΊ§n nΓ y cΓ³ cΓ‘c rule ΔΖ‘n giαΊ£n hΖ‘n. NhΖ°ng cΕ©ng sαΊ½ khΓ³ hΖ‘n tΓ vΓ¬ lượng dα»― liα»u khΓ‘ lα»n. NαΊΏu chΖ°a cΓ³ nhiα»u kinh nghiα»m xα» lΓ½ dα»― liα»u vΓ tα»i Ζ°u hΓ³a thΓ¬ cΓ³ thα» sαΊ½ khΓ΄ng kα»p thα»i gian lΓ m bΓ i (thα»i gian lΓ m cho challenge nΓ y lΓ 3 giα»).
Many thanks for my teammate @hoanghouit (Business Analyst), @XuanVuong (Business Analyst), @PhamVanMinh272 (Data Engineer), @nlchibao (ML Engineer).
#Logistics #Problem #Shopee #Code #League