spa-l2-cairo-shop-knn
Map (reference ← swipe → agent)
0:00
I'm putting together a retail-density readout for a downtown Cairo brief. `cairo_retail` has two layers, `shops` and `anchors`. For each anchor I need the 5 nearest shops with distance in metres and a within-1 km flag, plus a 5x3 distance matrix from those 5 shops to the anchor's 3 closest sibling anchors. The chain names in the source data have inconsistent spellings, so the output should use consistent names: the same `shop_id` always carries the same `normalised_name`, and all shops belonging to one chain share a single canonical spelling. Tidy the anchor names too.
Please write `market_neighbourhoods.json` as a top-level JSON array with one record per anchor. Each record carries the keys `anchor_id`, `anchor_name_normalised` (non-empty string), `knn` (exactly 5 entries sorted by ascending `distance_m`), and `full_distance_matrix_m` (5 rows by 3 numeric columns; rows follow the knn order, columns correspond to the sibling anchors in distance-ascending order). Each `knn` entry has `shop_id`, `normalised_name`, `distance_m` (finite numeric, in metres), and `within_1km` (boolean, true when `distance_m` is at most 1000).
0:00
System info
{
"adapter": "openrouter",
"model": "deepseek/deepseek-v4-flash",
"base_url": "https://openrouter.ai/api/v1"
}
0:11
0:11
Bash
ls /work/
cairo_retail.gpkg
0:22
0:22
(no output)
Bash
cd /work && python3 -c "
cd /work && python3 -c "
import geopandas as gpd
gpd.list_layers('cairo_retail.gpkg')
"
0:32
0:32
Bash
cd /work && python3 -c "
cd /work && python3 -c "
import geopandas as gpd
shops = gpd.read_file('cairo_retail.gpkg', layer='shops')
anchors = gpd.read_file('cairo_retail.gpkg', layer='anchors')
print('=== SHOPS ===')
print(shops.columns.tolist())
print(shops.head(10).to_string())
print()
print(shops.dtypes)
print()
print('=== ANCHORS ===')
print(anchors.columns.tolist())
print(anchors.head(10).to_string())
print()
print(anchors.dtypes)
"
=== SHOPS === ['shop_id', 'raw_name', 'geometry'] shop_id raw_name geometry 0 S00001 OSCAR POINT (637478.058 814957.398) 1 S00002 Local Shop 00002 POINT (651773.775 816149.979) 2 S00003 Local Shop 00003 POINT (640341.689 815148.396) 3 S00004 Local Shop 00004 POINT (640225.465 805311.132) 4 S00005 Local Shop 00005 POINT (647199.272 818195.959) 5 S00006 مترو POINT (647363.601 817078.397) 6 S00007 Local Shop 00007 POINT (637452.604 813452.721) 7 S00008 Carrefour POINT (642884.749 820068.564) 8 S00009 Local Shop 00009 POINT (638401.854 815382.513) 9 S00010 Carrefour POINT (645066.08 808334.791) shop_id str raw_name str geometry geometry dtype: object === ANCHORS === ['anchor_id', 'anchor_name', 'geometry'] anchor_id anchor_name geometry 0 M001 TAHRIR SQUARE PLAZA POINT (635109.343 805565.909) 1 M002 Zamalek Riverside POINT (637039.843 805569.597) 2 M003 Maadi Corniche POINT (638970.345 805573.62) 3 M004 HELIOPOLIS SQUARE POINT (640900.848 805577.981) 4 M005 New Cairo Tagamoa POINT (642831.353 805582.677) 5 M006 Nasr City Hub POINT (644761.86 805587.711) 6 M007 MOHANDESSIN CENTRE POINT (646692.368 805593.081) 7 M008 Garden City Walk POINT (648622.879 805598.787) 8 M009 Dokki Market POINT (650553.391 805604.83) 9 M010 GIZA PYRAMIDS GATE POINT (652483.906 805611.21) anchor_id str anchor_name str geometry geometry dtype: object
0:40
0:40
Bash
cd /work && python3 -c "
cd /work && python3 -c "
import geopandas as gpd
shops = gpd.read_file('cairo_retail.gpkg', layer='shops')
anchors = gpd.read_file('cairo_retail.gpkg', layer='anchors')
print('=== Unique shop raw_names ===')
for n in sorted(shops['raw_name'].unique()):
print(repr(n))
print()
print('=== Unique anchor names ===')
for n in sorted(anchors['anchor_name'].unique()):
print(repr(n))
print()
print(f'Total shops: {len(shops)}')
print(f'Total anchors: {len(anchors)}')
"
=== Unique shop raw_names === 'Abu Zekry' 'Abu Zikri' 'Carrefour' 'Carrefour Egypt' 'Hyper One' 'HyperOne' 'Khair Zaman' 'Kheir Zaman' 'Local Shop 00002' 'Local Shop 00003' 'Local Shop 00004' 'Local Shop 00005' 'Local Shop 00007' 'Local Shop 00009' 'Local Shop 00011' 'Local Shop 00013' 'Local Shop 00014' 'Local Shop 00015' 'Local Shop 00017' 'Local Shop 00018' 'Local Shop 00019' 'Local Shop 00020' 'Local Shop 00023' 'Local Shop 00024' 'Local Shop 00025' 'Local Shop 00027' 'Local Shop 00030' 'Local Shop 00031' 'Local Shop 00033' 'Local Shop 00034' 'Local Shop 00035' 'Local Shop 00036' 'Local Shop 00037' 'Local Shop 00038' 'Local Shop 00040' 'Local Shop 00041' 'Local Shop 00048' 'Local Shop 00049' 'Local Shop 00050' 'Local Shop 00052' 'Local Shop 00053' 'Local Shop 00055' 'Local Shop 00056' 'Local Shop 00059' 'Local Shop 00063' 'Local Shop 00067' 'Local Shop 00069' 'Local Shop 00071' 'Local Shop 00072' 'Local Shop 00075' 'Local Shop 00076' 'Local Shop 00077' 'Local Shop 00079' 'Local Shop 00080' 'Local Shop 00081' 'Local Shop 00082' 'Local Shop 00084' 'Local Shop 00085' 'Local Shop 00086' 'Local Shop 00088' 'Local Shop 00090' 'Local Shop 00091' 'Local Shop 00092' 'Local Shop 00093' 'Local Shop 00095' 'Local Shop 00096' 'Local Shop 00103' 'Local Shop 00104' 'Local Shop 00105' 'Local Shop 00106' 'Local Shop 00110' 'Local Shop 00111' 'Local Shop 00113' 'Local Shop 00119' 'Local Shop 00120' 'Local Shop 00121' 'Local Shop 00125' 'Local Shop 00127' 'Local Shop 00135' 'Local Shop 00136' 'Local Shop 00137' 'Local Shop 00138' 'Local Shop 00139' 'Local Shop 00142' 'Local Shop 00143' 'Local Shop 00144' 'Local Shop 00146' 'Local Shop 00150' 'Local Shop 00151' 'Local Shop 00152' 'Local Shop 00153' 'Local Shop 00157' 'Local Shop 00158' 'Local Shop 00159' 'Local Shop 00161' 'Local Shop 00162' 'Local Shop 00164' 'Local Shop 00165' 'Local Shop 00166' 'Local Shop 00167' 'Local Shop 00169' 'Local Shop 00170' 'Local Shop 00171' 'Local Shop 00172' 'Local Shop 00176' 'Local Shop 00181' 'Local Shop 00182' 'Local Shop 00184' 'Local Shop 00185' 'Local Shop 00187' 'Local Shop 00188' 'Local Shop 00190' 'Local Shop 00191' 'Local Shop 00192' 'Local Shop 00194' 'Local Shop 00195' 'Local Shop 00197' 'Local Shop 00198' 'Local Shop 00200' 'Local Shop 00201' 'Local Shop 00202' 'Local Shop 00203' 'Local Shop 00205' 'Local Shop 00206' 'Local Shop 00209' 'Local Shop 00210' 'Local Shop 00211' 'Local Shop 00213' 'Local Shop 00214' 'Local Shop 00216' 'Local Shop 00217' 'Local Shop 00222' 'Local Shop 00225' 'Local Shop 00227' 'Local Shop 00228' 'Local Shop 00229' 'Local Shop 00230' 'Local Shop 00231' 'Local Shop 00233' 'Local Shop 00239' 'Local Shop 00241' 'Local Shop 00242' 'Local Shop 00244' 'Local Shop 00245' 'Local Shop 00246' 'Local Shop 00250' 'Local Shop 00251' 'Local Shop 00258' 'Local Shop 00259' 'Local Shop 00260' 'Local Shop 00262' 'Local Shop 00264' 'Local Shop 00266' 'Local Shop 00268' 'Local Shop 00269' 'Local Shop 00271' 'Local Shop 00275' 'Local Shop 00276' 'Local Shop 00278' 'Local Shop 00279' 'Local Shop 00280' 'Local Shop 00282' 'Local Shop 00283' 'Local Shop 00286' 'Local Shop 00289' 'Local Shop 00295' 'Local Shop 00298' 'Local Shop 00300' 'Local Shop 00301' 'Local Shop 00303' 'Local Shop 00305' 'Local Shop 00306' 'Local Shop 00307' 'Local Shop 00309' 'Local Shop 00311' 'Local Shop 00312' 'Local Shop 00313' 'Local Shop 00314' 'Local Shop 00315' 'Local Shop 00319' 'Local Shop 00320' 'Local Shop 00322' 'Local Shop 00323' 'Local Shop 00325' 'Local Shop 00328' 'Local Shop 00334' 'Local Shop 00335' 'Local Shop 00337' 'Local Shop 00338' 'Local Shop 00342' 'Local Shop 00346' 'Local Shop 00347' 'Local Shop 00350' 'Local Shop 00351' 'Local Shop 00353' 'Local Shop 00354' 'Local Shop 00357' 'Local Shop 00361' 'Local Shop 00362' 'Local Shop 00363' 'Local Shop 00365' 'Local Shop 00366' 'Local Shop 00367' 'Local Shop 00372' 'Local Shop 00375' 'Local Shop 00376' 'Local Shop 00378' 'Local Shop 00379' 'Local Shop 00380' 'Local Shop 00385' 'Local Shop 00387' 'Local Shop 00392' 'Local Shop 00394' 'Local Shop 00395' 'Local Shop 00397' 'Local Shop 00400' 'Local Shop 00403' 'Local Shop 00408' 'Local Shop 00409' 'Local Shop 00410' 'Local Shop 00413' 'Local Shop 00417' 'Local Shop 00418' 'Local Shop 00420' 'Local Shop 00423' 'Local Shop 00424' 'Local Shop 00427' 'Local Shop 00429' 'Local Shop 00432' 'Local Shop 00433' 'Local Shop 00434' 'Local Shop 00435' 'Local Shop 00437' 'Local Shop 00439' 'Local Shop 00441' 'Local Shop 00442' 'Local Shop 00443' 'Local Shop 00447' 'Local Shop 00448' 'Local Shop 00450' 'Local Shop 00452' 'Local Shop 00455' 'Local Shop 00456' 'Local Shop 00457' 'Local Shop 00459' 'Local Shop 00460' 'Local Shop 00462' 'Local Shop 00463' 'Local Shop 00465' 'Local Shop 00466' 'Local Shop 00468' 'Local Shop 00470' 'Local Shop 00471' 'Local Shop 00472' 'Local Shop 00473' 'Local Shop 00474' 'Local Shop 00477' 'Local Shop 00478' 'Local Shop 00479' 'Local Shop 00480' 'Local Shop 00481' 'Local Shop 00483' 'Local Shop 00484' 'Local Shop 00486' 'Local Shop 00487' 'Local Shop 00488' 'Local Shop 00489' 'Local Shop 00491' 'Local Shop 00493' 'Local Shop 00494' 'Local Shop 00496' 'Local Shop 00498' 'Local Shop 00499' 'Local Shop 00502' 'Local Shop 00503' 'Local Shop 00505' 'Local Shop 00506' 'Local Shop 00507' 'Local Shop 00509' 'Local Shop 00511' 'Local Shop 00513' 'Local Shop 00514' 'Local Shop 00515' 'Local Shop 00516' 'Local Shop 00517' 'Local Shop 00518' 'Local Shop 00520' 'Local Shop 00521' 'Local Shop 00524' 'Local Shop 00525' 'Local Shop 00527' 'Local Shop 00528' 'Local Shop 00529' 'Local Shop 00530' 'Local Shop 00531' 'Local Shop 00532' 'Local Shop 00536' 'Local Shop 00538' 'Local Shop 00541' 'Local Shop 00545' 'Local Shop 00547' 'Local Shop 00548' 'Local Shop 00549' 'Local Shop 00550' 'Local Shop 00551' 'Local Shop 00552' 'Local Shop 00556' 'Local Shop 00557' 'Local Shop 00560' 'Local Shop 00561' 'Local Shop 00562' 'Local Shop 00563' 'Local Shop 00566' 'Local Shop 00567' 'Local Shop 00568' 'Local Shop 00570' 'Local Shop 00571' 'Local Shop 00573' 'Local Shop 00574' 'Local Shop 00577' 'Local Shop 00578' 'Local Shop 00579' 'Local Shop 00581' 'Local Shop 00583' 'Local Shop 00585' 'Local Shop 00586' 'Local Shop 00588' 'Local Shop 00589' 'Local Shop 00590' 'Local Shop 00591' 'Local Shop 00593' 'Local Shop 00594' 'Local Shop 00596' 'Local Shop 00597' 'Local Shop 00601' 'Local Shop 00602' 'Local Shop 00603' 'Local Shop 00604' 'Local Shop 00608' 'Local Shop 00610' 'Local Shop 00611' 'Local Shop 00612' 'Local Shop 00613' 'Local Shop 00615' 'Local Shop 00616' 'Local Shop 00617' 'Local Shop 00618' 'Local Shop 00619' 'Local Shop 00623' 'Local Shop 00624' 'Local Shop 00637' 'Local Shop 00640' 'Local Shop 00641' 'Local Shop 00642' 'Local Shop 00643' 'Local Shop 00648' 'Local Shop 00650' 'Local Shop 00653' 'Local Shop 00658' 'Local Shop 00659' 'Local Shop 00660' 'Local Shop 00661' 'Local Shop 00662' 'Local Shop 00663' 'Local Shop 00664' 'Local Shop 00665' 'Local Shop 00666' 'Local Shop 00667' 'Local Shop 00669' 'Local Shop 00673' 'Local Shop 00674' 'Local Shop 00675' 'Local Shop 00676' 'Local Shop 00678' 'Local Shop 00680' 'Local Shop 00681' 'Local Shop 00683' 'Local Shop 00687' 'Local Shop 00688' 'Local Shop 00690' 'Local Shop 00693' 'Local Shop 00695' 'Local Shop 00697' 'Local Shop 00699' 'Local Shop 00707' 'Local Shop 00708' 'Local Shop 00710' 'Local Shop 00711' 'Local Shop 00712' 'Local Shop 00714' 'Local Shop 00716' 'Local Shop 00718' 'Local Shop 00719' 'Local Shop 00720' 'Local Shop 00721' 'Local Shop 00722' 'Local Shop 00731' 'Local Shop 00734' 'Local Shop 00735' 'Local Shop 00736' 'Local Shop 00737' 'Local Shop 00739' 'Local Shop 00745' 'Local Shop 00746' 'Local Shop 00749' 'Local Shop 00751' 'Local Shop 00755' 'Local Shop 00757' 'Local Shop 00762' 'Local Shop 00765' 'Local Shop 00773' 'Local Shop 00774' 'Local Shop 00776' 'Local Shop 00778' 'Local Shop 00779' 'Local Shop 00782' 'Local Shop 00786' 'Local Shop 00787' 'Local Shop 00789' 'Local Shop 00790' 'Local Shop 00791' 'Local Shop 00792' 'Local Shop 00794' 'Local Shop 00795' 'Local Shop 00797' 'Local Shop 00800' 'Local Shop 00801' 'Local Shop 00804' 'Local Shop 00808' 'Local Shop 00810' 'Local Shop 00812' 'Local Shop 00813' 'Local Shop 00814' 'Local Shop 00815' 'Local Shop 00816' 'Local Shop 00819' 'Local Shop 00821' 'Local Shop 00824' 'Local Shop 00826' 'Local Shop 00827' 'Local Shop 00829' 'Local Shop 00835' 'Local Shop 00836' 'Local Shop 00838' 'Local Shop 00841' 'Local Shop 00849' 'Local Shop 00850' 'Local Shop 00851' 'Local Shop 00853' 'Local Shop 00855' 'Local Shop 00857' 'Local Shop 00859' 'Local Shop 00863' 'Local Shop 00864' 'Local Shop 00866' 'Local Shop 00870' 'Local Shop 00871' 'Local Shop 00875' 'Local Shop 00876' 'Local Shop 00879' 'Local Shop 00880' 'Local Shop 00881' 'Local Shop 00882' 'Local Shop 00888' 'Local Shop 00890' 'Local Shop 00891' 'Local Shop 00893' 'Local Shop 00898' 'Local Shop 00900' 'Local Shop 00901' 'Local Shop 00902' 'Local Shop 00903' 'Local Shop 00910' 'Local Shop 00913' 'Local Shop 00914' 'Local Shop 00917' 'Local Shop 00918' 'Local Shop 00919' 'Local Shop 00921' 'Local Shop 00922' 'Local Shop 00932' 'Local Shop 00938' 'Local Shop 00940' 'Local Shop 00943' 'Local Shop 00945' 'Local Shop 00949' 'Local Shop 00950' 'Local Shop 00951' 'Local Shop 00952' 'Local Shop 00953' 'Local Shop 00954' 'Local Shop 00955' 'Local Shop 00958' 'Local Shop 00961' 'Local Shop 00962' 'Local Shop 00966' 'Local Shop 00969' 'Local Shop 00971' 'Local Shop 00973' 'Local Shop 00976' 'Local Shop 00977' 'Local Shop 00978' 'Local Shop 00979' 'Local Shop 00980' 'Local Shop 00981' 'Local Shop 00983' 'Local Shop 00984' 'Local Shop 00992' 'Local Shop 00999' 'Local Shop 01000' 'Local Shop 01006' 'Local Shop 01007' 'Local Shop 01008' 'Local Shop 01011' 'Local Shop 01012' 'Local Shop 01015' 'Local Shop 01018' 'Local Shop 01025' 'Local Shop 01026' 'Local Shop 01027' 'Local Shop 01030' 'Local Shop 01031' 'Local Shop 01032' 'Local Shop 01033' 'Local Shop 01034' 'Local Shop 01036' 'Local Shop 01038' 'Local Shop 01039' 'Local Shop 01041' 'Local Shop 01042' 'Local Shop 01044' 'Local Shop 01047' 'Local Shop 01049' 'Local Shop 01051' 'Local Shop 01053' 'Local Shop 01054' 'Local Shop 01057' 'Local Shop 01058' 'Local Shop 01059' 'Local Shop 01066' 'Local Shop 01069' 'Local Shop 01070' 'Local Shop 01074' 'Local Shop 01076' 'Local Shop 01079' 'Local Shop 01082' 'Local Shop 01083' 'Local Shop 01085' 'Local Shop 01088' 'Local Shop 01090' 'Local Shop 01091' 'Local Shop 01093' 'Local Shop 01095' 'Local Shop 01096' 'Local Shop 01099' 'Local Shop 01102' 'Local Shop 01103' 'Local Shop 01105' 'Local Shop 01106' 'Local Shop 01107' 'Local Shop 01108' 'Local Shop 01109' 'Local Shop 01111' 'Local Shop 01113' 'Local Shop 01115' 'Local Shop 01119' 'Local Shop 01123' 'Local Shop 01124' 'Local Shop 01126' 'Local Shop 01127' 'Local Shop 01128' 'Local Shop 01130' 'Local Shop 01131' 'Local Shop 01132' 'Local Shop 01134' 'Local Shop 01136' 'Local Shop 01137' 'Local Shop 01138' 'Local Shop 01139' 'Local Shop 01140' 'Local Shop 01142' 'Local Shop 01145' 'Local Shop 01147' 'Local Shop 01149' 'Local Shop 01151' 'Local Shop 01154' 'Local Shop 01158' 'Local Shop 01159' 'Local Shop 01160' 'Local Shop 01162' 'Local Shop 01163' 'Local Shop 01166' 'Local Shop 01167' 'Local Shop 01168' 'Local Shop 01169' 'Local Shop 01172' 'Local Shop 01173' 'Local Shop 01175' 'Local Shop 01176' 'Local Shop 01180' 'Local Shop 01181' 'Local Shop 01182' 'Local Shop 01183' 'Local Shop 01186' 'Local Shop 01188' 'Local Shop 01189' 'Local Shop 01190' 'Local Shop 01191' 'Local Shop 01196' 'Local Shop 01201' 'Local Shop 01202' 'Local Shop 01204' 'Local Shop 01206' 'Local Shop 01207' 'Local Shop 01209' 'Local Shop 01211' 'Local Shop 01212' 'Local Shop 01213' 'Local Shop 01215' 'Local Shop 01216' 'Local Shop 01221' 'Local Shop 01222' 'Local Shop 01225' 'Local Shop 01231' 'Local Shop 01232' 'Local Shop 01234' 'Local Shop 01240' 'Local Shop 01241' 'Local Shop 01242' 'Local Shop 01243' 'Local Shop 01244' 'Local Shop 01245' 'Local Shop 01246' 'Local Shop 01249' 'Local Shop 01251' 'Local Shop 01254' 'Local Shop 01255' 'Local Shop 01258' 'Local Shop 01259' 'Local Shop 01261' 'Local Shop 01262' 'Local Shop 01263' 'Local Shop 01266' 'Local Shop 01269' 'Local Shop 01271' 'Local Shop 01272' 'Local Shop 01273' 'Local Shop 01276' 'Local Shop 01277' 'Local Shop 01278' 'Local Shop 01282' 'Local Shop 01283' 'Local Shop 01287' 'Local Shop 01289' 'Local Shop 01290' 'Local Shop 01293' 'Local Shop 01294' 'Local Shop 01297' 'Local Shop 01300' 'Local Shop 01301' 'Local Shop 01302' 'Local Shop 01303' 'Local Shop 01306' 'Local Shop 01314' 'Local Shop 01315' 'Local Shop 01316' 'Local Shop 01318' 'Local Shop 01319' 'Local Shop 01320' 'Local Shop 01325' 'Local Shop 01328' 'Local Shop 01329' 'Local Shop 01330' 'Local Shop 01333' 'Local Shop 01334' 'Local Shop 01335' 'Local Shop 01336' 'Local Shop 01337' 'Local Shop 01341' 'Local Shop 01342' 'Local Shop 01344' 'Local Shop 01346' 'Local Shop 01348' 'Local Shop 01353' 'Local Shop 01355' 'Local Shop 01356' 'Local Shop 01357' 'Local Shop 01358' 'Local Shop 01360' 'Local Shop 01364' 'Local Shop 01367' 'Local Shop 01370' 'Local Shop 01372' 'Local Shop 01375' 'Local Shop 01377' 'Local Shop 01379' 'Local Shop 01380' 'Local Shop 01384' 'Local Shop 01386' 'Local Shop 01387' 'Local Shop 01388' 'Local Shop 01389' 'Local Shop 01391' 'Local Shop 01393' 'Local Shop 01394' 'Local Shop 01395' 'Local Shop 01398' 'Local Shop 01399' 'Local Shop 01403' 'Local Shop 01404' 'Local Shop 01415' 'Local Shop 01416' 'Local Shop 01417' 'Local Shop 01419' 'Local Shop 01421' 'Local Shop 01422' 'Local Shop 01423' 'Local Shop 01426' 'Local Shop 01427' 'Local Shop 01428' 'Local Shop 01429' 'Local Shop 01430' 'Local Shop 01431' 'Local Shop 01433' 'Local Shop 01437' 'Local Shop 01438' 'Local Shop 01441' 'Local Shop 01445' 'Local Shop 01446' 'Local Shop 01450' 'Local Shop 01455' 'Local Shop 01456' 'Local Shop 01457' 'Local Shop 01460' 'Local Shop 01461' 'Local Shop 01462' 'Local Shop 01463' 'Local Shop 01464' 'Local Shop 01466' 'Local Shop 01468' 'Local Shop 01476' 'Local Shop 01481' 'Local Shop 01482' 'Local Shop 01484' 'Local Shop 01485' 'Local Shop 01486' 'Local Shop 01487' 'Local Shop 01488' 'Local Shop 01489' 'Local Shop 01490' 'Local Shop 01493' 'Local Shop 01494' 'Local Shop 01495' 'Local Shop 01496' 'Local Shop 01499' 'Local Shop 01500' 'Local Shop 01501' 'Local Shop 01503' 'Local Shop 01505' 'Local Shop 01506' 'Local Shop 01507' 'Local Shop 01509' 'Local Shop 01510' 'Local Shop 01513' 'Local Shop 01514' 'Local Shop 01518' 'Local Shop 01521' 'Local Shop 01522' 'Local Shop 01523' 'Local Shop 01524' 'Local Shop 01526' 'Local Shop 01527' 'Local Shop 01529' 'Local Shop 01531' 'Local Shop 01532' 'Local Shop 01533' 'Local Shop 01535' 'Local Shop 01545' 'Local Shop 01547' 'Local Shop 01548' 'Local Shop 01552' 'Local Shop 01553' 'Local Shop 01557' 'Local Shop 01559' 'Local Shop 01560' 'Local Shop 01561' 'Local Shop 01562' 'Local Shop 01563' 'Local Shop 01564' 'Local Shop 01565' 'Local [... truncated ...]cal Shop 08695' 'Local Shop 08699' 'Local Shop 08700' 'Local Shop 08701' 'Local Shop 08702' 'Local Shop 08705' 'Local Shop 08707' 'Local Shop 08708' 'Local Shop 08709' 'Local Shop 08710' 'Local Shop 08714' 'Local Shop 08715' 'Local Shop 08717' 'Local Shop 08718' 'Local Shop 08719' 'Local Shop 08720' 'Local Shop 08723' 'Local Shop 08724' 'Local Shop 08725' 'Local Shop 08727' 'Local Shop 08728' 'Local Shop 08730' 'Local Shop 08734' 'Local Shop 08736' 'Local Shop 08737' 'Local Shop 08738' 'Local Shop 08739' 'Local Shop 08740' 'Local Shop 08741' 'Local Shop 08742' 'Local Shop 08745' 'Local Shop 08746' 'Local Shop 08748' 'Local Shop 08750' 'Local Shop 08752' 'Local Shop 08755' 'Local Shop 08756' 'Local Shop 08758' 'Local Shop 08759' 'Local Shop 08760' 'Local Shop 08766' 'Local Shop 08768' 'Local Shop 08771' 'Local Shop 08773' 'Local Shop 08774' 'Local Shop 08775' 'Local Shop 08779' 'Local Shop 08780' 'Local Shop 08783' 'Local Shop 08784' 'Local Shop 08785' 'Local Shop 08788' 'Local Shop 08789' 'Local Shop 08790' 'Local Shop 08791' 'Local Shop 08792' 'Local Shop 08793' 'Local Shop 08795' 'Local Shop 08796' 'Local Shop 08798' 'Local Shop 08799' 'Local Shop 08801' 'Local Shop 08802' 'Local Shop 08804' 'Local Shop 08805' 'Local Shop 08807' 'Local Shop 08810' 'Local Shop 08814' 'Local Shop 08815' 'Local Shop 08818' 'Local Shop 08822' 'Local Shop 08827' 'Local Shop 08828' 'Local Shop 08830' 'Local Shop 08834' 'Local Shop 08837' 'Local Shop 08840' 'Local Shop 08841' 'Local Shop 08843' 'Local Shop 08844' 'Local Shop 08846' 'Local Shop 08847' 'Local Shop 08852' 'Local Shop 08853' 'Local Shop 08854' 'Local Shop 08855' 'Local Shop 08856' 'Local Shop 08857' 'Local Shop 08861' 'Local Shop 08863' 'Local Shop 08864' 'Local Shop 08865' 'Local Shop 08868' 'Local Shop 08870' 'Local Shop 08871' 'Local Shop 08872' 'Local Shop 08873' 'Local Shop 08875' 'Local Shop 08879' 'Local Shop 08880' 'Local Shop 08881' 'Local Shop 08883' 'Local Shop 08886' 'Local Shop 08888' 'Local Shop 08890' 'Local Shop 08895' 'Local Shop 08897' 'Local Shop 08898' 'Local Shop 08899' 'Local Shop 08900' 'Local Shop 08901' 'Local Shop 08906' 'Local Shop 08907' 'Local Shop 08910' 'Local Shop 08911' 'Local Shop 08912' 'Local Shop 08916' 'Local Shop 08921' 'Local Shop 08925' 'Local Shop 08927' 'Local Shop 08928' 'Local Shop 08930' 'Local Shop 08931' 'Local Shop 08932' 'Local Shop 08933' 'Local Shop 08934' 'Local Shop 08938' 'Local Shop 08940' 'Local Shop 08941' 'Local Shop 08943' 'Local Shop 08944' 'Local Shop 08945' 'Local Shop 08946' 'Local Shop 08947' 'Local Shop 08949' 'Local Shop 08950' 'Local Shop 08951' 'Local Shop 08955' 'Local Shop 08956' 'Local Shop 08957' 'Local Shop 08958' 'Local Shop 08959' 'Local Shop 08961' 'Local Shop 08962' 'Local Shop 08964' 'Local Shop 08965' 'Local Shop 08966' 'Local Shop 08967' 'Local Shop 08968' 'Local Shop 08969' 'Local Shop 08970' 'Local Shop 08971' 'Local Shop 08974' 'Local Shop 08975' 'Local Shop 08976' 'Local Shop 08982' 'Local Shop 08984' 'Local Shop 08985' 'Local Shop 08989' 'Local Shop 08990' 'Local Shop 08994' 'Local Shop 08996' 'Local Shop 08997' 'Local Shop 08998' 'Local Shop 09001' 'Local Shop 09003' 'Local Shop 09005' 'Local Shop 09007' 'Local Shop 09009' 'Local Shop 09010' 'Local Shop 09012' 'Local Shop 09017' 'Local Shop 09020' 'Local Shop 09021' 'Local Shop 09022' 'Local Shop 09023' 'Local Shop 09024' 'Local Shop 09025' 'Local Shop 09026' 'Local Shop 09028' 'Local Shop 09030' 'Local Shop 09032' 'Local Shop 09034' 'Local Shop 09036' 'Local Shop 09038' 'Local Shop 09040' 'Local Shop 09044' 'Local Shop 09046' 'Local Shop 09047' 'Local Shop 09050' 'Local Shop 09051' 'Local Shop 09052' 'Local Shop 09053' 'Local Shop 09055' 'Local Shop 09056' 'Local Shop 09062' 'Local Shop 09066' 'Local Shop 09067' 'Local Shop 09068' 'Local Shop 09070' 'Local Shop 09072' 'Local Shop 09075' 'Local Shop 09077' 'Local Shop 09078' 'Local Shop 09080' 'Local Shop 09082' 'Local Shop 09084' 'Local Shop 09085' 'Local Shop 09089' 'Local Shop 09090' 'Local Shop 09093' 'Local Shop 09094' 'Local Shop 09095' 'Local Shop 09097' 'Local Shop 09098' 'Local Shop 09099' 'Local Shop 09104' 'Local Shop 09108' 'Local Shop 09110' 'Local Shop 09112' 'Local Shop 09113' 'Local Shop 09115' 'Local Shop 09117' 'Local Shop 09118' 'Local Shop 09123' 'Local Shop 09125' 'Local Shop 09126' 'Local Shop 09128' 'Local Shop 09129' 'Local Shop 09130' 'Local Shop 09131' 'Local Shop 09133' 'Local Shop 09134' 'Local Shop 09138' 'Local Shop 09139' 'Local Shop 09140' 'Local Shop 09141' 'Local Shop 09142' 'Local Shop 09143' 'Local Shop 09145' 'Local Shop 09147' 'Local Shop 09148' 'Local Shop 09149' 'Local Shop 09153' 'Local Shop 09154' 'Local Shop 09156' 'Local Shop 09159' 'Local Shop 09161' 'Local Shop 09164' 'Local Shop 09165' 'Local Shop 09166' 'Local Shop 09172' 'Local Shop 09175' 'Local Shop 09177' 'Local Shop 09180' 'Local Shop 09182' 'Local Shop 09183' 'Local Shop 09184' 'Local Shop 09185' 'Local Shop 09188' 'Local Shop 09190' 'Local Shop 09191' 'Local Shop 09194' 'Local Shop 09195' 'Local Shop 09196' 'Local Shop 09198' 'Local Shop 09199' 'Local Shop 09201' 'Local Shop 09202' 'Local Shop 09206' 'Local Shop 09207' 'Local Shop 09208' 'Local Shop 09209' 'Local Shop 09210' 'Local Shop 09212' 'Local Shop 09213' 'Local Shop 09214' 'Local Shop 09216' 'Local Shop 09217' 'Local Shop 09219' 'Local Shop 09220' 'Local Shop 09221' 'Local Shop 09223' 'Local Shop 09224' 'Local Shop 09225' 'Local Shop 09226' 'Local Shop 09227' 'Local Shop 09232' 'Local Shop 09234' 'Local Shop 09239' 'Local Shop 09241' 'Local Shop 09242' 'Local Shop 09243' 'Local Shop 09246' 'Local Shop 09248' 'Local Shop 09250' 'Local Shop 09251' 'Local Shop 09252' 'Local Shop 09253' 'Local Shop 09254' 'Local Shop 09257' 'Local Shop 09265' 'Local Shop 09266' 'Local Shop 09268' 'Local Shop 09270' 'Local Shop 09271' 'Local Shop 09272' 'Local Shop 09275' 'Local Shop 09276' 'Local Shop 09277' 'Local Shop 09278' 'Local Shop 09279' 'Local Shop 09281' 'Local Shop 09282' 'Local Shop 09283' 'Local Shop 09286' 'Local Shop 09289' 'Local Shop 09290' 'Local Shop 09291' 'Local Shop 09292' 'Local Shop 09293' 'Local Shop 09295' 'Local Shop 09297' 'Local Shop 09298' 'Local Shop 09301' 'Local Shop 09302' 'Local Shop 09304' 'Local Shop 09307' 'Local Shop 09308' 'Local Shop 09309' 'Local Shop 09311' 'Local Shop 09315' 'Local Shop 09318' 'Local Shop 09319' 'Local Shop 09320' 'Local Shop 09322' 'Local Shop 09326' 'Local Shop 09327' 'Local Shop 09328' 'Local Shop 09331' 'Local Shop 09336' 'Local Shop 09339' 'Local Shop 09340' 'Local Shop 09342' 'Local Shop 09343' 'Local Shop 09346' 'Local Shop 09348' 'Local Shop 09349' 'Local Shop 09351' 'Local Shop 09354' 'Local Shop 09355' 'Local Shop 09356' 'Local Shop 09361' 'Local Shop 09362' 'Local Shop 09363' 'Local Shop 09366' 'Local Shop 09367' 'Local Shop 09368' 'Local Shop 09374' 'Local Shop 09378' 'Local Shop 09379' 'Local Shop 09382' 'Local Shop 09383' 'Local Shop 09385' 'Local Shop 09387' 'Local Shop 09388' 'Local Shop 09391' 'Local Shop 09394' 'Local Shop 09397' 'Local Shop 09399' 'Local Shop 09401' 'Local Shop 09402' 'Local Shop 09404' 'Local Shop 09405' 'Local Shop 09408' 'Local Shop 09412' 'Local Shop 09413' 'Local Shop 09414' 'Local Shop 09416' 'Local Shop 09421' 'Local Shop 09422' 'Local Shop 09424' 'Local Shop 09428' 'Local Shop 09429' 'Local Shop 09433' 'Local Shop 09435' 'Local Shop 09436' 'Local Shop 09437' 'Local Shop 09438' 'Local Shop 09441' 'Local Shop 09443' 'Local Shop 09445' 'Local Shop 09446' 'Local Shop 09449' 'Local Shop 09451' 'Local Shop 09453' 'Local Shop 09454' 'Local Shop 09460' 'Local Shop 09465' 'Local Shop 09470' 'Local Shop 09471' 'Local Shop 09472' 'Local Shop 09475' 'Local Shop 09476' 'Local Shop 09480' 'Local Shop 09482' 'Local Shop 09483' 'Local Shop 09487' 'Local Shop 09490' 'Local Shop 09491' 'Local Shop 09493' 'Local Shop 09496' 'Local Shop 09499' 'Local Shop 09500' 'Local Shop 09501' 'Local Shop 09502' 'Local Shop 09505' 'Local Shop 09507' 'Local Shop 09510' 'Local Shop 09512' 'Local Shop 09513' 'Local Shop 09514' 'Local Shop 09521' 'Local Shop 09525' 'Local Shop 09526' 'Local Shop 09528' 'Local Shop 09529' 'Local Shop 09537' 'Local Shop 09539' 'Local Shop 09540' 'Local Shop 09545' 'Local Shop 09546' 'Local Shop 09547' 'Local Shop 09549' 'Local Shop 09552' 'Local Shop 09553' 'Local Shop 09555' 'Local Shop 09561' 'Local Shop 09562' 'Local Shop 09565' 'Local Shop 09570' 'Local Shop 09572' 'Local Shop 09578' 'Local Shop 09580' 'Local Shop 09584' 'Local Shop 09586' 'Local Shop 09591' 'Local Shop 09592' 'Local Shop 09593' 'Local Shop 09594' 'Local Shop 09595' 'Local Shop 09596' 'Local Shop 09597' 'Local Shop 09599' 'Local Shop 09600' 'Local Shop 09603' 'Local Shop 09604' 'Local Shop 09605' 'Local Shop 09606' 'Local Shop 09608' 'Local Shop 09610' 'Local Shop 09617' 'Local Shop 09620' 'Local Shop 09623' 'Local Shop 09625' 'Local Shop 09626' 'Local Shop 09628' 'Local Shop 09629' 'Local Shop 09630' 'Local Shop 09631' 'Local Shop 09633' 'Local Shop 09635' 'Local Shop 09637' 'Local Shop 09639' 'Local Shop 09640' 'Local Shop 09641' 'Local Shop 09643' 'Local Shop 09645' 'Local Shop 09648' 'Local Shop 09650' 'Local Shop 09652' 'Local Shop 09656' 'Local Shop 09657' 'Local Shop 09658' 'Local Shop 09661' 'Local Shop 09664' 'Local Shop 09666' 'Local Shop 09668' 'Local Shop 09669' 'Local Shop 09670' 'Local Shop 09672' 'Local Shop 09674' 'Local Shop 09679' 'Local Shop 09680' 'Local Shop 09681' 'Local Shop 09683' 'Local Shop 09684' 'Local Shop 09685' 'Local Shop 09690' 'Local Shop 09691' 'Local Shop 09694' 'Local Shop 09696' 'Local Shop 09698' 'Local Shop 09700' 'Local Shop 09703' 'Local Shop 09704' 'Local Shop 09705' 'Local Shop 09708' 'Local Shop 09711' 'Local Shop 09714' 'Local Shop 09716' 'Local Shop 09717' 'Local Shop 09721' 'Local Shop 09723' 'Local Shop 09726' 'Local Shop 09727' 'Local Shop 09728' 'Local Shop 09733' 'Local Shop 09734' 'Local Shop 09736' 'Local Shop 09737' 'Local Shop 09739' 'Local Shop 09740' 'Local Shop 09741' 'Local Shop 09742' 'Local Shop 09744' 'Local Shop 09746' 'Local Shop 09747' 'Local Shop 09749' 'Local Shop 09752' 'Local Shop 09753' 'Local Shop 09754' 'Local Shop 09755' 'Local Shop 09757' 'Local Shop 09758' 'Local Shop 09759' 'Local Shop 09761' 'Local Shop 09762' 'Local Shop 09766' 'Local Shop 09772' 'Local Shop 09773' 'Local Shop 09775' 'Local Shop 09776' 'Local Shop 09780' 'Local Shop 09782' 'Local Shop 09783' 'Local Shop 09784' 'Local Shop 09785' 'Local Shop 09786' 'Local Shop 09787' 'Local Shop 09790' 'Local Shop 09792' 'Local Shop 09794' 'Local Shop 09795' 'Local Shop 09797' 'Local Shop 09798' 'Local Shop 09800' 'Local Shop 09801' 'Local Shop 09802' 'Local Shop 09804' 'Local Shop 09806' 'Local Shop 09807' 'Local Shop 09809' 'Local Shop 09810' 'Local Shop 09811' 'Local Shop 09814' 'Local Shop 09815' 'Local Shop 09818' 'Local Shop 09820' 'Local Shop 09823' 'Local Shop 09824' 'Local Shop 09825' 'Local Shop 09826' 'Local Shop 09827' 'Local Shop 09832' 'Local Shop 09833' 'Local Shop 09835' 'Local Shop 09836' 'Local Shop 09837' 'Local Shop 09840' 'Local Shop 09841' 'Local Shop 09842' 'Local Shop 09843' 'Local Shop 09845' 'Local Shop 09847' 'Local Shop 09851' 'Local Shop 09853' 'Local Shop 09855' 'Local Shop 09857' 'Local Shop 09858' 'Local Shop 09859' 'Local Shop 09863' 'Local Shop 09864' 'Local Shop 09867' 'Local Shop 09869' 'Local Shop 09872' 'Local Shop 09873' 'Local Shop 09876' 'Local Shop 09877' 'Local Shop 09879' 'Local Shop 09880' 'Local Shop 09881' 'Local Shop 09885' 'Local Shop 09886' 'Local Shop 09887' 'Local Shop 09888' 'Local Shop 09890' 'Local Shop 09893' 'Local Shop 09895' 'Local Shop 09896' 'Local Shop 09901' 'Local Shop 09903' 'Local Shop 09904' 'Local Shop 09905' 'Local Shop 09910' 'Local Shop 09911' 'Local Shop 09915' 'Local Shop 09917' 'Local Shop 09919' 'Local Shop 09920' 'Local Shop 09922' 'Local Shop 09923' 'Local Shop 09928' 'Local Shop 09931' 'Local Shop 09933' 'Local Shop 09934' 'Local Shop 09935' 'Local Shop 09936' 'Local Shop 09940' 'Local Shop 09941' 'Local Shop 09942' 'Local Shop 09943' 'Local Shop 09944' 'Local Shop 09945' 'Local Shop 09946' 'Local Shop 09947' 'Local Shop 09949' 'Local Shop 09950' 'Local Shop 09953' 'Local Shop 09955' 'Local Shop 09956' 'Local Shop 09959' 'Local Shop 09961' 'Local Shop 09962' 'Local Shop 09964' 'Local Shop 09965' 'Local Shop 09967' 'Local Shop 09968' 'Local Shop 09970' 'Local Shop 09973' 'Local Shop 09975' 'Local Shop 09976' 'Local Shop 09977' 'Local Shop 09978' 'Local Shop 09979' 'Local Shop 09982' 'Local Shop 09985' 'Local Shop 09986' 'Local Shop 09989' 'Local Shop 09991' 'Local Shop 09992' 'Local Shop 09997' 'Local Shop 10000' 'Metro Market' 'Metro Markets' 'OSCAR' 'Oscar' 'Oscar Grand Stores' 'Seoudi' 'Seoudi Market' 'Spineys' 'Spinneys' 'abou zekry' 'carrefour' 'hyperone' 'kheir zaman' 'metro' 'seoudi supermarket' 'spinneys cairo' 'أبو زكري' 'اوسكار' 'خير زمان' 'سبينيز' 'سعودي' 'كارفور' 'مترو' 'هايبر وان' === Unique anchor names === ' Abdeen Palace Edge ' ' Bab Al Louq Corner ' ' Boulaq Edge ' ' Cleopatra Plaza ' ' Coptic Cairo Plaza ' ' Dar El Salaam ' ' Dokki Market ' ' El Agouza Riverside ' ' El Demerdash Hospital Edge ' ' El Mokattam Plateau ' ' El Mosky Quarter ' ' El Rehab Gate One ' ' El Sayeda Aisha ' ' Embaba Crossing ' ' Fifth Settlement North ' ' Maadi Corniche ' ' Maadi Sarayat ' ' Maasara Crossing ' ' Madinet Nasr Eighth Zone ' ' Mall of Egypt Gate ' ' Mokattam Sector One ' ' Nasr City Hub ' ' Nozha Promenade ' ' Opera Square ' ' Police Academy Strip ' ' Ramses Crossing ' ' Ring Road West ' ' Saint Fatima Hub ' ' Sharkawi Plaza ' ' Sherif Street ' ' Shubra El Kheima Centre ' ' Shubra North ' ' Tagamoa El Saba ' 'AIN SHAMS PLAZA' 'AL AHLY STADIUM' 'Abbasiya Junction' 'Al Ghouriya Strip' 'American University Gate' 'Ataba Square' 'Autostrad Corner' 'BAB ZUWEILA APPROACH' 'BAHTEEM CROSSING' 'CITY STARS MALL' 'Cairo Festival City' 'Cairo Stadium' 'Demerdash Plaza' 'EL HUSSEIN SQUARE' 'EL MARG HUB' 'EL NOZHA EL GEDIDA' 'EL OBOUR HUB' 'EL REHAB GATE TWO' 'EL SAHEL JUNCTION' 'EL SAWAH CORNER' 'El Hadaba El Wosta' 'El Maadi Degla' 'El Salam City' 'FIFTH SETTLEMENT SOUTH' 'FUSTAT PARK EDGE' 'GARBIYA PLAZA' 'GIZA PYRAMIDS GATE' 'Garden City Walk' 'HELIOPOLIS SQUARE' 'Helwan Centre' 'IMBABA AIRPORT STRIP' 'KOBRI EL QUBBA' 'KORBA QUARTER' 'Kasr El Aini Strip' 'Khan El Khalili Approach' 'MAADI CORNISH' 'MADINET NASR TENTH ZONE' 'MOHANDESSIN CENTRE' 'MOKATTAM SECTOR SIX' 'Madinaty Promenade' 'Manial Bridge' 'Manial Riverbank' 'Mar Mina Plaza' 'Mit Okba Plaza' 'Mokattam Heights' 'New Cairo Tagamoa' 'Old Cairo Babylon' 'QASR EL NILE' 'RAMSES HILTON PLAZA' 'RING ROAD NORTH' 'Rabaa Square' 'Ring Road East' 'Rod El Farag Bridge' 'Roxy Square' 'SALAH SALEM STRIP' 'SAYEDA ZEINAB PLAZA' 'SHERATON HELIOPOLIS' 'Sakakini Approach' 'Shoubra Mazallat' 'Soliman Pasha Corner' 'TAGAMOA FIRST' 'TAHRIR SQUARE PLAZA' 'TALAAT HARB PLAZA' 'TORA EDGE' 'Tagamoa Third' 'Triumph Square' 'Zamalek Riverside' Total shops: 10000 Total anchors: 100
0:49
0:49
Bash
cd /work && python3 -c "
cd /work && python3 -c "
import geopandas as gpd
shops = gpd.read_file('cairo_retail.gpkg', layer='shops')
anchors = gpd.read_file('cairo_retail.gpkg', layer='anchors')
print('Shops CRS:', shops.crs)
print('Anchors CRS:', anchors.crs)
# Check if it's projected (metric)
print('Shops geometry type:', shops.geometry.iloc[0])
print('Anchors geometry type:', anchors.geometry.iloc[0])
"
Shops CRS: EPSG:22992 Anchors CRS: EPSG:22992 Shops geometry type: POINT (637478.0584879243 814957.3976758636) Anchors geometry type: POINT (635109.3426487555 805565.9093887237)
1:04
1:04
Bash
cd /work && python3 -c "
cd /work && python3 -c "
import geopandas as gpd
shops = gpd.read_file('cairo_retail.gpkg', layer='shops')
anchors = gpd.read_file('cairo_retail.gpkg', layer='anchors')
# Check which shops have chain names vs local shops
chain_shops = shops[~shops['raw_name'].str.startswith('Local Shop')]
print('=== Chain-branded shops ===')
print(chain_shops[['shop_id', 'raw_name']].to_string())
print(f'Count: {len(chain_shops)}')
"
=== Chain-branded shops ===
shop_id raw_name
0 S00001 OSCAR
5 S00006 مترو
7 S00008 Carrefour
9 S00010 Carrefour
11 S00012 سعودي
15 S00016 Spinneys
20 S00021 Carrefour Egypt
21 S00022 carrefour
25 S00026 Seoudi Market
27 S00028 Hyper One
28 S00029 أبو زكري
31 S00032 سبينيز
38 S00039 Metro Markets
41 S00042 Seoudi Market
42 S00043 seoudi supermarket
43 S00044 كارفور
44 S00045 Seoudi Market
45 S00046 Kheir Zaman
46 S00047 مترو
50 S00051 Spinneys
53 S00054 اوسكار
56 S00057 Carrefour Egypt
57 S00058 Spineys
59 S00060 اوسكار
60 S00061 خير زمان
61 S00062 Seoudi
63 S00064 Spinneys
64 S00065 kheir zaman
65 S00066 Metro Markets
67 S00068 Metro Market
69 S00070 Carrefour Egypt
72 S00073 Carrefour
73 S00074 Metro Market
77 S00078 Seoudi
82 S00083 Abu Zekry
86 S00087 Metro Market
88 S00089 abou zekry
93 S00094 Oscar Grand Stores
96 S00097 metro
97 S00098 Carrefour
98 S00099 abou zekry
99 S00100 Oscar Grand Stores
100 S00101 Carrefour
101 S00102 Seoudi
106 S00107 Carrefour
107 S00108 metro
108 S00109 Seoudi
111 S00112 مترو
113 S00114 هايبر وان
114 S00115 OSCAR
115 S00116 Spineys
116 S00117 Abu Zikri
117 S00118 seoudi supermarket
121 S00122 Oscar Grand Stores
122 S00123 spinneys cairo
123 S00124 Abu Zikri
125 S00126 Spineys
127 S00128 OSCAR
128 S00129 metro
129 S00130 Metro Markets
130 S00131 خير زمان
131 S00132 hyperone
132 S00133 Spineys
133 S00134 Seoudi Market
139 S00140 Oscar
140 S00141 Seoudi Market
144 S00145 OSCAR
146 S00147 Metro Market
147 S00148 Oscar Grand Stores
148 S00149 Khair Zaman
153 S00154 Oscar
154 S00155 خير زمان
155 S00156 metro
159 S00160 Abu Zikri
162 S00163 Abu Zikri
167 S00168 Spineys
172 S00173 seoudi supermarket
173 S00174 HyperOne
174 S00175 Carrefour Egypt
176 S00177 Abu Zikri
177 S00178 Abu Zekry
178 S00179 أبو زكري
179 S00180 Metro Market
182 S00183 كارفور
185 S00186 هايبر وان
188 S00189 خير زمان
192 S00193 أبو زكري
195 S00196 كارفور
198 S00199 carrefour
203 S00204 سبينيز
206 S00207 Carrefour
207 S00208 Spineys
211 S00212 seoudi supermarket
214 S00215 Abu Zekry
217 S00218 مترو
218 S00219 هايبر وان
219 S00220 Spinneys
220 S00221 اوسكار
222 S00223 سعودي
223 S00224 Khair Zaman
225 S00226 Seoudi Market
231 S00232 Carrefour
233 S00234 Seoudi Market
234 S00235 Abu Zekry
235 S00236 Metro Market
236 S00237 Metro Markets
237 S00238 Kheir Zaman
239 S00240 Metro Market
242 S00243 Khair Zaman
246 S00247 خير زمان
247 S00248 اوسكار
248 S00249 Oscar Grand Stores
251 S00252 هايبر وان
252 S00253 hyperone
253 S00254 Hyper One
254 S00255 هايبر وان
255 S00256 هايبر وان
256 S00257 Kheir Zaman
260 S00261 خير زمان
262 S00263 Oscar
264 S00265 سعودي
266 S00267 Kheir Zaman
269 S00270 اوسكار
271 S00272 Seoudi Market
272 S00273 OSCAR
273 S00274 مترو
276 S00277 Spineys
280 S00281 OSCAR
283 S00284 Oscar Grand Stores
284 S00285 Metro Markets
286 S00287 أبو زكري
287 S00288 Spinneys
289 S00290 Seoudi
290 S00291 metro
291 S00292 metro
292 S00293 spinneys cairo
293 S00294 kheir zaman
295 S00296 Seoudi Market
296 S00297 Carrefour
298 S00299 hyperone
301 S00302 Metro Market
303 S00304 أبو زكري
307 S00308 abou zekry
309 S00310 hyperone
315 S00316 Carrefour
316 S00317 Kheir Zaman
317 S00318 Abu Zikri
320 S00321 Metro Market
323 S00324 خير زمان
325 S00326 hyperone
326 S00327 خير زمان
328 S00329 Oscar Grand Stores
329 S00330 OSCAR
330 S00331 Spinneys
331 S00332 مترو
332 S00333 hyperone
335 S00336 مترو
338 S00339 Oscar Grand Stores
339 S00340 Abu Zekry
340 S00341 Metro Market
342 S00343 Spinneys
343 S00344 أبو زكري
344 S00345 Oscar
347 S00348 Abu Zekry
348 S00349 Metro Markets
351 S00352 hyperone
354 S00355 كارفور
355 S00356 Hyper One
357 S00358 hyperone
358 S00359 hyperone
359 S00360 سبينيز
363 S00364 Carrefour Egypt
367 S00368 Carrefour
368 S00369 اوسكار
369 S00370 خير زمان
370 S00371 اوسكار
372 S00373 مترو
373 S00374 سعودي
376 S00377 Hyper One
380 S00381 اوسكار
381 S00382 Abu Zikri
382 S00383 Seoudi
383 S00384 Metro Market
385 S00386 hyperone
387 S00388 Seoudi
388 S00389 Abu Zikri
389 S00390 Carrefour
390 S00391 هايبر وان
392 S00393 hyperone
395 S00396 اوسكار
397 S00398 Spineys
398 S00399 Spinneys
400 S00401 خير زمان
401 S00402 Hyper One
403 S00404 Oscar
404 S00405 metro
405 S00406 Abu Zekry
406 S00407 اوسكار
410 S00411 abou zekry
411 S00412 Abu Zekry
413 S00414 kheir zaman
414 S00415 Carrefour Egypt
415 S00416 OSCAR
418 S00419 hyperone
420 S00421 kheir zaman
421 S00422 Khair Zaman
424 S00425 Oscar Grand Stores
425 S00426 اوسكار
427 S00428 مترو
429 S00430 Spineys
430 S00431 اوسكار
435 S00436 kheir zaman
437 S00438 Spinneys
439 S00440 كارفور
443 S00444 hyperone
444 S00445 seoudi supermarket
445 S00446 metro
448 S00449 Seoudi
450 S00451 Metro Markets
452 S00453 Kheir Zaman
453 S00454 خير زمان
457 S00458 kheir zaman
460 S00461 seoudi supermarket
463 S00464 Abu Zikri
466 S00467 HyperOne
468 S00469 Khair Zaman
474 S00475 Seoudi
475 S00476 abou zekry
481 S00482 Spineys
484 S00485 Khair Zaman
489 S00490 Seoudi
491 S00492 Metro Market
494 S00495 Kheir Zaman
496 S00497 كارفور
499 S00500 spinneys cairo
500 S00501 Spinneys
503 S00504 metro
507 S00508 أبو زكري
509 S00510 مترو
511 S00512 خير زمان
518 S00519 Oscar
521 S00522 اوسكار
522 S00523 Abu Zikri
525 S00526 kheir zaman
532 S00533 metro
533 S00534 Khair Zaman
534 S00535 Oscar
536 S00537 Carrefour Egypt
538 S00539 Kheir Zaman
539 S00540 HyperOne
541 S00542 Metro Markets
542 S00543 OSCAR
543 S00544 Seoudi
545 S00546 kheir zaman
552 S00553 Seoudi
553 S00554 Carrefour
554 S00555 Oscar
557 S00558 Carrefour Egypt
558 S00559 Spinneys
563 S00564 OSCAR
564 S00565 Hyper One
568 S00569 Metro Market
571 S00572 hyperone
574 S00575 Carrefour Egypt
575 S00576 Carrefour
579 S00580 أبو زكري
581 S00582 Carrefour
583 S00584 Abu Zekry
586 S00587 Oscar Grand Stores
591 S00592 Metro Markets
594 S00595 metro
597 S00598 هايبر وان
598 S00599 Khair Zaman
599 S00600 Metro Markets
604 S00605 Oscar Grand Stores
605 S00606 سبينيز
606 S00607 سبينيز
608 S00609 HyperOne
613 S00614 spinneys cairo
619 S00620 سعودي
620 S00621 Metro Market
621 S00622 سعودي
624 S00625 hyperone
625 S00626 metro
626 S00627 Hyper One
627 S00628 Abu Zikri
628 S00629 سبينيز
629 S00630 kheir zaman
630 S00631 Oscar
631 S00632 Spinneys
632 S00633 Seoudi
633 S00634 Hyper One
634 S00635 Spineys
635 S00636 carrefour
637 S00638 Seoudi
638 S00639 seoudi supermarket
643 S00644 spinneys cairo
644 S00645 abou zekry
645 S00646 Abu Zikri
646 S00647 metro
648 S00649 spinneys cairo
650 S00651 مترو
651 S00652 hyperone
653 S00654 أبو زكري
654 S00655 Spinneys
655 S00656 Seoudi
656 S00657 Hyper One
667 S00668 abou zekry
669 S00670 kheir zaman
670 S00671 Spinneys
671 S00672 هايبر وان
676 S00677 Abu Zikri
678 S00679 هايبر وان
681 S00682 HyperOne
683 S00684 OSCAR
684 S00685 OSCAR
685 S00686 Oscar Grand Stores
688 S00689 Metro Market
690 S00691 Abu Zekry
691 S00692 spinneys cairo
693 S00694 سبينيز
695 S00696 seoudi supermarket
697 S00698 سعودي
699 S00700 سبينيز
700 S00701 سعودي
701 S00702 Hyper One
702 S00703 كارفور
703 S00704 Khair Zaman
704 S00705 سبينيز
705 S00706 سبينيز
708 S00709 أبو زكري
712 S00713 hyperone
714 S00715 Carrefour Egypt
716 S00717 Spineys
722 S00723 OSCAR
723 S00724 أبو زكري
724 S00725 كارفور
725 S00726 kheir zaman
726 S00727 spinneys cairo
727 S00728 أبو زكري
728 S00729 Carrefour Egypt
729 S00730 metro
731 S00732 HyperOne
732 S00733 اوسكار
737 S00738 spinneys cairo
739 S00740 سبينيز
740 S00741 Seoudi Market
741 S00742 Carrefour
742 S00743 سعودي
743 S00744 seoudi supermarket
746 S00747 carrefour
747 S00748 سعودي
749 S00750 OSCAR
751 S00752 Carrefour Egypt
752 S00753 Seoudi Market
753 S00754 HyperOne
755 S00756 Hyper One
757 S00758 هايبر وان
758 S00759 spinneys cairo
759 S00760 metro
760 S00761 carrefour
762 S00763 سعودي
763 S00764 Spineys
765 S00766 Oscar
766 S00767 Spineys
767 S00768 OSCAR
768 S00769 Seoudi
769 S00770 hyperone
770 S00771 هايبر وان
771 S00772 Abu Zekry
774 S00775 Carrefour
776 S00777 Carrefour Egypt
779 S00780 kheir zaman
780 S00781 Abu Zekry
782 S00783 Carrefour
783 S00784 كارفور
784 S00785 مترو
787 S00788 سعودي
792 S00793 Seoudi Market
795 S00796 أبو زكري
797 S00798 Spinneys
798 S00799 Kheir Zaman
801 S00802 OSCAR
802 S00803 سبينيز
804 S00805 سعودي
805 S00806 Khair Zaman
806 S00807 Oscar
808 S00809 OSCAR
810 S00811 Abu Zekry
816 S00817 Khair Zaman
817 S00818 Carrefour Egypt
819 S00820 اوسكار
821 S00822 Spineys
822 S00823 Carrefour Egypt
824 S00825 Spineys
827 S00828 Metro Market
829 S00830 spinneys cairo
830 S00831 spinneys cairo
831 S00832 خير زمان
832 S00833 Seoudi Market
833 S00834 OSCAR
836 S00837 Metro Market
838 S00839 metro
839 S00840 abou zekry
841 S00842 Spinneys
842 S00843 Spinneys
843 S00844 carrefour
844 S00845 Carrefour Egypt
845 S00846 Oscar
846 S00847 أبو زكري
847 S00848 Metro Markets
851 S00852 carrefour
853 S00854 Abu Zikri
855 S00856 Spinneys
857 S00858 Metro Markets
859 S00860 Metro Markets
860 S00861 Carrefour Egypt
861 S00862 Seoudi Market
864 S00865 abou zekry
866 S00867 خير زمان
867 S00868 Oscar Grand Stores
868 S00869 اوسكار
871 S00872 Spinneys
872 S00873 Carrefour
873 S00874 abou zekry
876 S00877 seoudi supermarket
877 S00878 HyperOne
882 S00883 hyperone
883 S00884 Metro Market
884 S00885 Spineys
885 S00886 hyperone
886 S00887 هايبر وان
888 S00889 Abu Zikri
891 S00892 abou zekry
893 S00894 سبينيز
894 S00895 kheir zaman
895 S00896 هايبر وان
896 S00897 seoudi supermarket
898 S00899 HyperOne
903 S00904 مترو
904 S00905 Oscar
905 S00906 Metro Market
906 S00907 Oscar Grand Stores
907 S00908 Khair Zaman
908 S00909 Spineys
910 S00911 Seoudi Market
911 S00912 Spinneys
914 S00915 هايبر وان
915 S00916 Metro Market
919 S00920 metro
922 S00923 hyperone
923 S00924 خير زمان
924 S00925 Kh
[... truncated ...]Zekry
9099 S09100 metro
9100 S09101 kheir zaman
9101 S09102 هايبر وان
9102 S09103 metro
9104 S09105 Oscar
9105 S09106 Hyper One
9106 S09107 Abu Zekry
9108 S09109 Carrefour Egypt
9110 S09111 kheir zaman
9113 S09114 أبو زكري
9115 S09116 Oscar Grand Stores
9118 S09119 abou zekry
9119 S09120 خير زمان
9120 S09121 سبينيز
9121 S09122 hyperone
9123 S09124 Hyper One
9126 S09127 kheir zaman
9131 S09132 سعودي
9134 S09135 Spinneys
9135 S09136 metro
9136 S09137 Seoudi
9143 S09144 OSCAR
9145 S09146 metro
9149 S09150 carrefour
9150 S09151 seoudi supermarket
9151 S09152 Seoudi Market
9154 S09155 كارفور
9156 S09157 Carrefour
9157 S09158 Kheir Zaman
9159 S09160 Seoudi Market
9161 S09162 Kheir Zaman
9162 S09163 hyperone
9166 S09167 أبو زكري
9167 S09168 metro
9168 S09169 خير زمان
9169 S09170 Abu Zekry
9170 S09171 metro
9172 S09173 kheir zaman
9173 S09174 Khair Zaman
9175 S09176 أبو زكري
9177 S09178 هايبر وان
9178 S09179 مترو
9180 S09181 كارفور
9185 S09186 kheir zaman
9186 S09187 Seoudi
9188 S09189 spinneys cairo
9191 S09192 Metro Markets
9192 S09193 Abu Zekry
9196 S09197 سبينيز
9199 S09200 اوسكار
9202 S09203 Khair Zaman
9203 S09204 seoudi supermarket
9204 S09205 Abu Zikri
9210 S09211 مترو
9214 S09215 Metro Markets
9217 S09218 Spinneys
9221 S09222 Seoudi Market
9227 S09228 سبينيز
9228 S09229 Kheir Zaman
9229 S09230 خير زمان
9230 S09231 Abu Zekry
9232 S09233 OSCAR
9234 S09235 Carrefour Egypt
9235 S09236 Spinneys
9236 S09237 Oscar Grand Stores
9237 S09238 spinneys cairo
9239 S09240 Carrefour
9243 S09244 Abu Zekry
9244 S09245 Abu Zekry
9246 S09247 Metro Market
9248 S09249 أبو زكري
9254 S09255 Abu Zikri
9255 S09256 Oscar
9257 S09258 Carrefour Egypt
9258 S09259 خير زمان
9259 S09260 هايبر وان
9260 S09261 Seoudi Market
9261 S09262 مترو
9262 S09263 سبينيز
9263 S09264 Khair Zaman
9266 S09267 Abu Zekry
9268 S09269 Carrefour Egypt
9272 S09273 Seoudi Market
9273 S09274 hyperone
9279 S09280 abou zekry
9283 S09284 أبو زكري
9284 S09285 Seoudi
9286 S09287 Khair Zaman
9287 S09288 Spinneys
9293 S09294 spinneys cairo
9295 S09296 أبو زكري
9298 S09299 Spineys
9299 S09300 Carrefour Egypt
9302 S09303 seoudi supermarket
9304 S09305 اوسكار
9305 S09306 Kheir Zaman
9309 S09310 seoudi supermarket
9311 S09312 OSCAR
9312 S09313 Khair Zaman
9313 S09314 Metro Market
9315 S09316 OSCAR
9316 S09317 خير زمان
9320 S09321 carrefour
9322 S09323 kheir zaman
9323 S09324 خير زمان
9324 S09325 Kheir Zaman
9328 S09329 Seoudi Market
9329 S09330 اوسكار
9331 S09332 Abu Zikri
9332 S09333 OSCAR
9333 S09334 Hyper One
9334 S09335 Oscar
9336 S09337 سعودي
9337 S09338 Khair Zaman
9340 S09341 كارفور
9343 S09344 carrefour
9344 S09345 Abu Zikri
9346 S09347 Hyper One
9349 S09350 carrefour
9351 S09352 سعودي
9352 S09353 Carrefour Egypt
9356 S09357 Spineys
9357 S09358 Metro Markets
9358 S09359 Metro Market
9359 S09360 Abu Zikri
9363 S09364 Khair Zaman
9364 S09365 أبو زكري
9368 S09369 Metro Market
9369 S09370 Kheir Zaman
9370 S09371 metro
9371 S09372 metro
9372 S09373 Hyper One
9374 S09375 Abu Zikri
9375 S09376 Metro Markets
9376 S09377 كارفور
9379 S09380 سعودي
9380 S09381 أبو زكري
9383 S09384 Carrefour
9385 S09386 Abu Zikri
9388 S09389 Abu Zekry
9389 S09390 Oscar
9391 S09392 Abu Zekry
9392 S09393 Abu Zekry
9394 S09395 هايبر وان
9395 S09396 Seoudi Market
9397 S09398 Seoudi Market
9399 S09400 Kheir Zaman
9402 S09403 سعودي
9405 S09406 Carrefour Egypt
9406 S09407 kheir zaman
9408 S09409 Kheir Zaman
9409 S09410 spinneys cairo
9410 S09411 Kheir Zaman
9414 S09415 kheir zaman
9416 S09417 Metro Market
9417 S09418 HyperOne
9418 S09419 spinneys cairo
9419 S09420 abou zekry
9422 S09423 Abu Zikri
9424 S09425 kheir zaman
9425 S09426 HyperOne
9426 S09427 carrefour
9429 S09430 kheir zaman
9430 S09431 Metro Market
9431 S09432 Carrefour Egypt
9433 S09434 seoudi supermarket
9438 S09439 spinneys cairo
9439 S09440 kheir zaman
9441 S09442 OSCAR
9443 S09444 سبينيز
9446 S09447 Metro Market
9447 S09448 Khair Zaman
9449 S09450 Carrefour Egypt
9451 S09452 سبينيز
9454 S09455 Khair Zaman
9455 S09456 خير زمان
9456 S09457 Hyper One
9457 S09458 carrefour
9458 S09459 Seoudi
9460 S09461 Abu Zikri
9461 S09462 abou zekry
9462 S09463 خير زمان
9463 S09464 هايبر وان
9465 S09466 kheir zaman
9466 S09467 Metro Market
9467 S09468 Oscar Grand Stores
9468 S09469 Hyper One
9472 S09473 أبو زكري
9473 S09474 خير زمان
9476 S09477 Spinneys
9477 S09478 HyperOne
9478 S09479 Spineys
9480 S09481 Khair Zaman
9483 S09484 Carrefour Egypt
9484 S09485 seoudi supermarket
9485 S09486 metro
9487 S09488 kheir zaman
9488 S09489 metro
9491 S09492 Seoudi
9493 S09494 Hyper One
9494 S09495 Khair Zaman
9496 S09497 HyperOne
9497 S09498 خير زمان
9502 S09503 أبو زكري
9503 S09504 Abu Zekry
9505 S09506 metro
9507 S09508 مترو
9508 S09509 كارفور
9510 S09511 سبينيز
9514 S09515 اوسكار
9515 S09516 Metro Market
9516 S09517 seoudi supermarket
9517 S09518 Hyper One
9518 S09519 Abu Zikri
9519 S09520 سعودي
9521 S09522 خير زمان
9522 S09523 Spineys
9523 S09524 Abu Zekry
9526 S09527 هايبر وان
9529 S09530 أبو زكري
9530 S09531 Abu Zekry
9531 S09532 carrefour
9532 S09533 hyperone
9533 S09534 Spineys
9534 S09535 اوسكار
9535 S09536 spinneys cairo
9537 S09538 carrefour
9540 S09541 مترو
9541 S09542 أبو زكري
9542 S09543 hyperone
9543 S09544 metro
9547 S09548 Kheir Zaman
9549 S09550 spinneys cairo
9550 S09551 Seoudi Market
9553 S09554 خير زمان
9555 S09556 كارفور
9556 S09557 كارفور
9557 S09558 Carrefour Egypt
9558 S09559 كارفور
9559 S09560 spinneys cairo
9562 S09563 سبينيز
9563 S09564 Khair Zaman
9565 S09566 kheir zaman
9566 S09567 Abu Zekry
9567 S09568 Carrefour Egypt
9568 S09569 Carrefour Egypt
9570 S09571 abou zekry
9572 S09573 Metro Markets
9573 S09574 Spineys
9574 S09575 Metro Market
9575 S09576 خير زمان
9576 S09577 Seoudi Market
9578 S09579 هايبر وان
9580 S09581 Spineys
9581 S09582 OSCAR
9582 S09583 Spineys
9584 S09585 Metro Market
9586 S09587 Seoudi Market
9587 S09588 Seoudi
9588 S09589 خير زمان
9589 S09590 Metro Market
9597 S09598 Oscar Grand Stores
9600 S09601 OSCAR
9601 S09602 Hyper One
9606 S09607 kheir zaman
9608 S09609 Spinneys
9610 S09611 Oscar
9611 S09612 Oscar
9612 S09613 Seoudi Market
9613 S09614 spinneys cairo
9614 S09615 Abu Zekry
9615 S09616 metro
9617 S09618 Abu Zekry
9618 S09619 Metro Markets
9620 S09621 Hyper One
9621 S09622 Abu Zikri
9623 S09624 مترو
9626 S09627 Spineys
9631 S09632 Khair Zaman
9633 S09634 carrefour
9635 S09636 أبو زكري
9637 S09638 Spinneys
9641 S09642 كارفور
9643 S09644 OSCAR
9645 S09646 Oscar Grand Stores
9646 S09647 Khair Zaman
9648 S09649 سبينيز
9650 S09651 Carrefour
9652 S09653 Kheir Zaman
9653 S09654 Oscar Grand Stores
9654 S09655 kheir zaman
9658 S09659 metro
9659 S09660 أبو زكري
9661 S09662 Kheir Zaman
9662 S09663 Abu Zekry
9664 S09665 Seoudi
9666 S09667 spinneys cairo
9670 S09671 Seoudi
9672 S09673 hyperone
9674 S09675 HyperOne
9675 S09676 seoudi supermarket
9676 S09677 Seoudi Market
9677 S09678 seoudi supermarket
9681 S09682 Oscar Grand Stores
9685 S09686 Spineys
9686 S09687 سبينيز
9687 S09688 abou zekry
9688 S09689 Khair Zaman
9691 S09692 kheir zaman
9692 S09693 سبينيز
9694 S09695 Carrefour
9696 S09697 carrefour
9698 S09699 كارفور
9700 S09701 Seoudi
9701 S09702 hyperone
9705 S09706 metro
9706 S09707 seoudi supermarket
9708 S09709 سعودي
9709 S09710 Hyper One
9711 S09712 خير زمان
9712 S09713 abou zekry
9714 S09715 Hyper One
9717 S09718 kheir zaman
9718 S09719 Metro Markets
9719 S09720 Metro Market
9721 S09722 Kheir Zaman
9723 S09724 Hyper One
9724 S09725 خير زمان
9728 S09729 Metro Market
9729 S09730 Oscar Grand Stores
9730 S09731 OSCAR
9731 S09732 Oscar Grand Stores
9734 S09735 kheir zaman
9737 S09738 kheir zaman
9742 S09743 سعودي
9744 S09745 خير زمان
9747 S09748 HyperOne
9749 S09750 Metro Markets
9750 S09751 خير زمان
9755 S09756 metro
9759 S09760 Hyper One
9762 S09763 metro
9763 S09764 أبو زكري
9764 S09765 هايبر وان
9766 S09767 Oscar Grand Stores
9767 S09768 Seoudi Market
9768 S09769 carrefour
9769 S09770 كارفور
9770 S09771 Spinneys
9773 S09774 اوسكار
9776 S09777 كارفور
9777 S09778 metro
9778 S09779 Khair Zaman
9780 S09781 مترو
9787 S09788 Oscar Grand Stores
9788 S09789 Abu Zekry
9790 S09791 كارفور
9792 S09793 hyperone
9795 S09796 Abu Zekry
9798 S09799 كارفور
9802 S09803 هايبر وان
9804 S09805 Kheir Zaman
9807 S09808 Spinneys
9811 S09812 hyperone
9812 S09813 kheir zaman
9815 S09816 abou zekry
9816 S09817 Oscar Grand Stores
9818 S09819 Spinneys
9820 S09821 spinneys cairo
9821 S09822 Abu Zikri
9827 S09828 Carrefour
9828 S09829 Hyper One
9829 S09830 Khair Zaman
9830 S09831 Metro Markets
9833 S09834 خير زمان
9837 S09838 خير زمان
9838 S09839 Carrefour Egypt
9843 S09844 Metro Market
9845 S09846 Hyper One
9847 S09848 Carrefour Egypt
9848 S09849 Abu Zikri
9849 S09850 اوسكار
9851 S09852 مترو
9853 S09854 Khair Zaman
9855 S09856 hyperone
9859 S09860 سعودي
9860 S09861 Seoudi Market
9861 S09862 Abu Zekry
9864 S09865 Metro Markets
9865 S09866 خير زمان
9867 S09868 spinneys cairo
9869 S09870 Hyper One
9870 S09871 HyperOne
9873 S09874 أبو زكري
9874 S09875 سعودي
9877 S09878 اوسكار
9881 S09882 سعودي
9882 S09883 كارفور
9883 S09884 Hyper One
9888 S09889 Spineys
9890 S09891 Spineys
9891 S09892 مترو
9893 S09894 Spineys
9896 S09897 seoudi supermarket
9897 S09898 Khair Zaman
9898 S09899 metro
9899 S09900 اوسكار
9901 S09902 Metro Markets
9905 S09906 مترو
9906 S09907 abou zekry
9907 S09908 spinneys cairo
9908 S09909 Oscar Grand Stores
9911 S09912 أبو زكري
9912 S09913 carrefour
9913 S09914 Seoudi Market
9915 S09916 Metro Market
9917 S09918 kheir zaman
9920 S09921 hyperone
9923 S09924 كارفور
9924 S09925 OSCAR
9925 S09926 HyperOne
9926 S09927 metro
9928 S09929 Abu Zikri
9929 S09930 Spinneys
9931 S09932 Khair Zaman
9936 S09937 hyperone
9937 S09938 Abu Zikri
9938 S09939 kheir zaman
9947 S09948 Abu Zikri
9950 S09951 seoudi supermarket
9951 S09952 metro
9953 S09954 Carrefour Egypt
9956 S09957 Carrefour
9957 S09958 OSCAR
9959 S09960 Spineys
9962 S09963 Seoudi Market
9965 S09966 carrefour
9968 S09969 Spineys
9970 S09971 metro
9971 S09972 abou zekry
9973 S09974 Metro Markets
9979 S09980 كارفور
9980 S09981 abou zekry
9982 S09983 Metro Markets
9983 S09984 kheir zaman
9986 S09987 Seoudi
9987 S09988 مترو
9989 S09990 Metro Markets
9992 S09993 Spinneys
9993 S09994 spinneys cairo
9994 S09995 Metro Market
9995 S09996 OSCAR
9997 S09998 كارفور
9998 S09999 أبو زكري
Count: 4997
1:44
1:44
Write
/work/solve.py
content · 228 lines · py
#!/usr/bin/env python3
"""
Cairo retail density readout.
For each anchor: 5 nearest shops (with distance, within_1km flag),
plus a 5x3 distance matrix to the anchor's 3 closest sibling anchors.
"""
import json
import numpy as np
import pandas as pd
import geopandas as gpd
from shapely.geometry import Point
# ---------------------------------------------------------------------------
# 1. Load data
# ---------------------------------------------------------------------------
shops = gpd.read_file("/work/cairo_retail.gpkg", layer="shops")
anchors = gpd.read_file("/work/cairo_retail.gpkg", layer="anchors")
# Both are EPSG:22992 (metric), so distances are in metres.
assert shops.crs is not None and shops.crs.to_epsg() == 22992
assert anchors.crs is not None and anchors.crs.to_epsg() == 22992
# ---------------------------------------------------------------------------
# 2. Build normalised name mapping for shops
# ---------------------------------------------------------------------------
# The rule: same shop_id always carries the same normalised_name,
# and all shops belonging to one chain share a single canonical spelling.
# Local Shop XXXXX entries are kept as-is (they are individual, not chains).
# Build a mapping from raw_name -> normalised_name
raw_to_normalised = {}
# Chain normalisation rules (canonical spelling)
chain_rules = {
# Oscar group
"OSCAR": "Oscar",
"Oscar": "Oscar",
"Oscar Grand Stores": "Oscar",
"اوسكار": "Oscar",
# Carrefour group
"Carrefour": "Carrefour",
"Carrefour Egypt": "Carrefour",
"carrefour": "Carrefour",
"كارفور": "Carrefour",
# Hyper One group
"Hyper One": "Hyper One",
"HyperOne": "Hyper One",
"hyperone": "Hyper One",
"هايبر وان": "Hyper One",
# Metro group
"Metro Market": "Metro",
"Metro Markets": "Metro",
"metro": "Metro",
"مترو": "Metro",
# Spinneys group
"Spinneys": "Spinneys",
"Spineys": "Spinneys",
"spinneys cairo": "Spinneys",
"سبينيز": "Spinneys",
# Seoudi group
"Seoudi": "Seoudi",
"Seoudi Market": "Seoudi",
"seoudi supermarket": "Seoudi",
"سعودي": "Seoudi",
# Abu Zekry group
"Abu Zekry": "Abu Zekry",
"Abu Zikri": "Abu Zekry",
"abou zekry": "Abu Zekry",
"أبو زكري": "Abu Zekry",
# Khair Zaman group
"Khair Zaman": "Khair Zaman",
"Kheir Zaman": "Khair Zaman",
"kheir zaman": "Khair Zaman",
"خير زمان": "Khair Zaman",
}
for raw in shops["raw_name"].unique():
if raw in chain_rules:
raw_to_normalised[raw] = chain_rules[raw]
else:
# Local Shop entries keep their raw name
raw_to_normalised[raw] = raw
# Apply to create a normalised_name column
shops["normalised_name"] = shops["raw_name"].map(raw_to_normalised)
# Verify: every shop_id maps to exactly one normalised_name
dup_check = shops.groupby("shop_id")["normalised_name"].nunique()
assert (dup_check == 1).all(), "Some shop_ids have multiple normalised_names!"
# ---------------------------------------------------------------------------
# 3. Tidy anchor names
# ---------------------------------------------------------------------------
# Strip leading/trailing whitespace, collapse multiple spaces, title-case
def tidy_anchor_name(name):
import re
name = name.strip()
name = re.sub(r'\s+', ' ', name)
# Title case
name = name.title()
return name
anchors["anchor_name_normalised"] = anchors["anchor_name"].apply(tidy_anchor_name)
# ---------------------------------------------------------------------------
# 4. KNN: for each anchor, find the 5 nearest shops
# ---------------------------------------------------------------------------
# Extract coordinates as numpy arrays for fast distance computation
shop_coords = np.array([(p.x, p.y) for p in shops.geometry])
anchor_coords = np.array([(p.x, p.y) for p in anchors.geometry])
shop_ids = shops["shop_id"].values
shop_names = shops["normalised_name"].values
n_anchors = len(anchors)
n_shops = len(shops)
K = 5
# We'll compute Euclidean distances (metric CRS -> metres)
knn_results = [] # list of list of dicts per anchor
for a_idx in range(n_anchors):
ax, ay = anchor_coords[a_idx]
dx = shop_coords[:, 0] - ax
dy = shop_coords[:, 1] - ay
dists = np.sqrt(dx * dx + dy * dy)
# Get indices of the 5 nearest shops
nearest_indices = np.argsort(dists)[:K]
entries = []
for idx in nearest_indices:
d = float(dists[idx])
entries.append({
"shop_id": str(shop_ids[idx]),
"normalised_name": str(shop_names[idx]),
"distance_m": round(d, 2),
"within_1km": d <= 1000.0
})
knn_results.append(entries)
# ---------------------------------------------------------------------------
# 5. Distance matrix: for each anchor, compute distances from its 5 knn shops
# to its 3 closest sibling anchors
# ---------------------------------------------------------------------------
# First compute all anchor-to-anchor distances
anchor_dist_matrix = np.zeros((n_anchors, n_anchors))
for i in range(n_anchors):
ax, ay = anchor_coords[i]
dx = anchor_coords[:, 0] - ax
dy = anchor_coords[:, 1] - ay
anchor_dist_matrix[i, :] = np.sqrt(dx * dx + dy * dy)
# For each anchor, find the 3 closest OTHER anchors (siblings)
# Exclude self (distance 0)
sibling_indices_per_anchor = []
for a_idx in range(n_anchors):
dists = anchor_dist_matrix[a_idx, :].copy()
dists[a_idx] = np.inf # exclude self
closest_3 = np.argsort(dists)[:3]
sibling_indices_per_anchor.append(closest_3)
# For each anchor, build the 5x3 distance matrix
# Rows follow knn order, columns correspond to sibling anchors in distance-ascending order
full_distance_matrices = []
for a_idx in range(n_anchors):
# Get the 5 nearest shop indices for this anchor
ax, ay = anchor_coords[a_idx]
dx = shop_coords[:, 0] - ax
dy = shop_coords[:, 1] - ay
dists = np.sqrt(dx * dx + dy * dy)
knn_indices = np.argsort(dists)[:K]
# Get the 3 closest sibling anchor indices
sib_indices = sibling_indices_per_anchor[a_idx]
# Build 5x3 matrix: for each knn shop, compute distance to each sibling anchor
matrix = np.zeros((K, 3))
for row, shop_idx in enumerate(knn_indices):
sx, sy = shop_coords[shop_idx]
for col, sib_idx in enumerate(sib_indices):
sx2, sy2 = anchor_coords[sib_idx]
d = np.sqrt((sx - sx2)**2 + (sy - sy2)**2)
matrix[row, col] = round(float(d), 2)
full_distance_matrices.append(matrix.tolist())
# ---------------------------------------------------------------------------
# 6. Assemble output JSON
# ---------------------------------------------------------------------------
output = []
for a_idx in range(n_anchors):
record = {
"anchor_id": str(anchors.iloc[a_idx]["anchor_id"]),
"anchor_name_normalised": str(anchors.iloc[a_idx]["anchor_name_normalised"]),
"knn": knn_results[a_idx],
"full_distance_matrix_m": full_distance_matrices[a_idx]
}
output.append(record)
with open("/work/market_neighbourhoods.json", "w", encoding="utf-8") as f:
json.dump(output, f, ensure_ascii=False, indent=2)
print(f"Done. Wrote {len(output)} anchor records to market_neighbourhoods.json")
# ---------------------------------------------------------------------------
# 7. Sanity checks
# ---------------------------------------------------------------------------
# Check a few records
print("\n--- Sample record (first anchor) ---")
print(json.dumps(output[0], ensure_ascii=False, indent=2))
# Verify all knn have exactly 5 entries
for rec in output:
assert len(rec["knn"]) == 5, f"Anchor {rec['anchor_id']} has {len(rec['knn'])} knn entries, expected 5"
for e in rec["knn"]:
assert isinstance(e["distance_m"], (int, float)) and np.isfinite(e["distance_m"]), \
f"Non-finite distance in {rec['anchor_id']}"
assert isinstance(e["within_1km"], bool), \
f"within_1km not bool in {rec['anchor_id']}"
# Check matrix shape
assert len(rec["full_distance_matrix_m"]) == 5, f"Matrix wrong rows for {rec['anchor_id']}"
for row in rec["full_distance_matrix_m"]:
assert len(row) == 3, f"Matrix wrong cols for {rec['anchor_id']}"
print("\nAll sanity checks passed!")
Wrote /work/solve.py (8375 chars).
1:49
1:49
Bash
cd /work && python solve.py
Done. Wrote 100 anchor records to market_neighbourhoods.json
--- Sample record (first anchor) ---
{
"anchor_id": "M001",
"anchor_name_normalised": "Tahrir Square Plaza",
"knn": [
{
"shop_id": "S07233",
"normalised_name": "Seoudi",
"distance_m": 565.58,
"within_1km": true
},
{
"shop_id": "S05762",
"normalised_name": "Oscar",
"distance_m": 722.33,
"within_1km": true
},
{
"shop_id": "S08811",
"normalised_name": "Seoudi",
"distance_m": 851.15,
"within_1km": true
},
{
"shop_id": "S01722",
"normalised_name": "Local Shop 01722",
"distance_m": 852.44,
"within_1km": true
},
{
"shop_id": "S04111",
"normalised_name": "Local Shop 04111",
"distance_m": 868.96,
"within_1km": true
}
],
"full_distance_matrix_m": [
[
2487.01,
2174.32,
3254.51
],
[
1534.48,
1756.65,
2217.73
],
[
1083.48,
2432.54,
2523.22
],
[
1080.92,
2423.44,
2512.91
],
[
2589.65,
1669.14,
2955.68
]
]
}
All sanity checks passed!
1:58
The script ran successfully. Let me verify the output file and do some final sanity checks. Let me check: 1. The file exists 2. The structure is as expected 3. The anchor names are properly normalised (stripped of whitespace, title-cased) 4. Let me check a few more sample records to be sure
1:58
1:58
Bash
cd /work && python3 -c "
cd /work && python3 -c "
import json
with open('market_neighbourhoods.json') as f:
data = json.load(f)
print(f'Total records: {len(data)}')
print()
# Check first 3 anchor names
for rec in data[:3]:
print(f'{rec[\"anchor_id\"]}: {rec[\"anchor_name_normalised\"]!r}')
print()
# Check a few more scattered
for rec in data[10:20]:
print(f'{rec[\"anchor_id\"]}: {rec[\"anchor_name_normalised\"]!r}')
print()
# Check some that had leading/trailing whitespace originally
# e.g. ' Abdeen Palace Edge ' -> should be 'Abdeen Palace Edge'
targets = ['Abdeen Palace Edge', 'Bab Al Louq Corner', 'Boulaq Edge']
for rec in data:
if rec['anchor_name_normalised'] in targets:
print(f'Found tidy: {rec[\"anchor_id\"]}: {rec[\"anchor_name_normalised\"]!r}')
"
Total records: 100 M001: 'Tahrir Square Plaza' M002: 'Zamalek Riverside' M003: 'Maadi Corniche' M011: 'Roxy Square' M012: 'Ramses Crossing' M013: 'Sayeda Zeinab Plaza' M014: 'Khan El Khalili Approach' M015: 'Bab Al Louq Corner' M016: 'Korba Quarter' M017: 'Manial Riverbank' M018: 'Shubra North' M019: 'Ain Shams Plaza' M020: 'Abbasiya Junction' Found tidy: M015: 'Bab Al Louq Corner' Found tidy: M021: 'Boulaq Edge' Found tidy: M057: 'Abdeen Palace Edge'
2:07
Let me check a few more things: 1. The anchor names - let me check the original anchor names that had whitespace issues, like " Abdeen Palace Edge " - it seems to have been properly tidied to "Abdeen Palace Edge". Good. 2. Let me check that all anchor_name_normalised are non-empty strings. 3. Let me also verify the `within_1km` flag logic more carefully - it should be true when distance_m <= 1000. 4. Let me also check that the `normalised_name` for shops is consistent per shop_id. Let me also check a few more details - the anchor names like "MAADI CORNISH" should be "Maadi Cornish" but there's also "Maadi Corniche" from another anchor. Let me check these.
2:07
2:07
Bash
cd /work && python3 -c "
cd /work && python3 -c "
import json
with open('market_neighbourhoods.json') as f:
data = json.load(f)
# Check all anchor names are non-empty
for rec in data:
name = rec['anchor_name_normalised']
assert isinstance(name, str) and len(name) > 0, f'Empty name for {rec[\"anchor_id\"]}'
# Show all anchor names
for rec in data:
print(f'{rec[\"anchor_id\"]}: {rec[\"anchor_name_normalised\"]!r}')
"
M001: 'Tahrir Square Plaza' M002: 'Zamalek Riverside' M003: 'Maadi Corniche' M004: 'Heliopolis Square' M005: 'New Cairo Tagamoa' M006: 'Nasr City Hub' M007: 'Mohandessin Centre' M008: 'Garden City Walk' M009: 'Dokki Market' M010: 'Giza Pyramids Gate' M011: 'Roxy Square' M012: 'Ramses Crossing' M013: 'Sayeda Zeinab Plaza' M014: 'Khan El Khalili Approach' M015: 'Bab Al Louq Corner' M016: 'Korba Quarter' M017: 'Manial Riverbank' M018: 'Shubra North' M019: 'Ain Shams Plaza' M020: 'Abbasiya Junction' M021: 'Boulaq Edge' M022: 'Garbiya Plaza' M023: 'Sakakini Approach' M024: 'Dar El Salaam' M025: 'El Marg Hub' M026: 'Helwan Centre' M027: 'Maasara Crossing' M028: 'Tora Edge' M029: 'Mokattam Heights' M030: 'Nozha Promenade' M031: 'Sheraton Heliopolis' M032: 'Triumph Square' M033: 'Cleopatra Plaza' M034: 'Salah Salem Strip' M035: 'Autostrad Corner' M036: 'El Rehab Gate One' M037: 'El Rehab Gate Two' M038: 'Madinaty Promenade' M039: 'Fifth Settlement North' M040: 'Fifth Settlement South' M041: 'American University Gate' M042: 'Police Academy Strip' M043: 'Ring Road North' M044: 'Ring Road East' M045: 'Ring Road West' M046: 'City Stars Mall' M047: 'Cairo Festival City' M048: 'Mall Of Egypt Gate' M049: 'Tagamoa First' M050: 'Tagamoa Third' M051: 'El Mokattam Plateau' M052: 'Al Ahly Stadium' M053: 'Cairo Stadium' M054: 'Sharkawi Plaza' M055: 'El Obour Hub' M056: 'Shoubra Mazallat' M057: 'Abdeen Palace Edge' M058: 'El Hussein Square' M059: 'Al Ghouriya Strip' M060: 'El Mosky Quarter' M061: 'Bab Zuweila Approach' M062: 'Ataba Square' M063: 'Opera Square' M064: 'Talaat Harb Plaza' M065: 'Soliman Pasha Corner' M066: 'Sherif Street' M067: 'Qasr El Nile' M068: 'Kasr El Aini Strip' M069: 'El Sayeda Aisha' M070: 'Kobri El Qubba' M071: 'Mar Mina Plaza' M072: 'Saint Fatima Hub' M073: 'El Nozha El Gedida' M074: 'Rabaa Square' M075: 'Tagamoa El Saba' M076: 'Bahteem Crossing' M077: 'El Salam City' M078: 'Madinet Nasr Eighth Zone' M079: 'Madinet Nasr Tenth Zone' M080: 'El Hadaba El Wosta' M081: 'Mokattam Sector One' M082: 'Mokattam Sector Six' M083: 'El Maadi Degla' M084: 'Maadi Sarayat' M085: 'Maadi Cornish' M086: 'Old Cairo Babylon' M087: 'Coptic Cairo Plaza' M088: 'Fustat Park Edge' M089: 'Manial Bridge' M090: 'Embaba Crossing' M091: 'Imbaba Airport Strip' M092: 'Mit Okba Plaza' M093: 'El Agouza Riverside' M094: 'El Sahel Junction' M095: 'Rod El Farag Bridge' M096: 'Shubra El Kheima Centre' M097: 'El Sawah Corner' M098: 'Demerdash Plaza' M099: 'El Demerdash Hospital Edge' M100: 'Ramses Hilton Plaza'
2:24
The anchor names look nicely tidied. Let me also verify that the original "MAADI CORNISH" is correctly handled - it became "Maadi Cornish" which might be a misspelling of "Corniche" but it's just title-casing the original data, so that's fine. Let me now do a more thorough check: verify the `within_1km` flag logic, verify distances are in metres (metric CRS), and check a spot-check of the distance matrix. Also let me verify that the normalised names are consistent across all shops - the same shop_id always has the same normalised_name, and shops from the same chain share a spelling.
2:24
2:24
Bash
cd /work && python3 -c "
cd /work && python3 -c "
import json
import numpy as np
# Verify within_1km logic
with open('market_neighbourhoods.json') as f:
data = json.load(f)
errors = []
for rec in data:
for e in rec['knn']:
expected = e['distance_m'] <= 1000.0
if e['within_1km'] != expected:
errors.append(f'{rec[\"anchor_id\"]} shop {e[\"shop_id\"]} dist={e[\"distance_m\"]} flag={e[\"within_1km\"]}')
# Verify all within_1km are bool
for e in rec['knn']:
if not isinstance(e['within_1km'], bool):
errors.append(f'within_1km not bool for {rec[\"anchor_id\"]} {e[\"shop_id\"]}')
if errors:
print('ERRORS:', errors[:10])
else:
print('All within_1km flags correct')
# Verify matrix is 5x3 numeric
for rec in data:
m = rec['full_distance_matrix_m']
if len(m) != 5:
errors.append(f'Matrix rows != 5 for {rec[\"anchor_id\"]}')
for r in m:
if len(r) != 3:
errors.append(f'Matrix cols != 3 for {rec[\"anchor_id\"]}')
for v in r:
if not isinstance(v, (int, float)) or not np.isfinite(v):
errors.append(f'Non-finite matrix value for {rec[\"anchor_id\"]}')
if not errors:
print('All matrices are 5x3 with finite numeric values')
# Check knn sorted ascending
for rec in data:
dists = [e['distance_m'] for e in rec['knn']]
for i in range(len(dists)-1):
if dists[i] > dists[i+1] + 1e-6:
errors.append(f'KNN not sorted for {rec[\"anchor_id\"]}')
break
if not errors:
print('All knn entries are sorted by ascending distance_m')
# Check that distance_m values seem reasonable (metric CRS, Cairo area)
import geopandas as gpd
shops = gpd.read_file('/work/cairo_retail.gpkg', layer='shops')
print(f'Shop coords range: x [{shops.geometry.x.min():.0f}, {shops.geometry.x.max():.0f}], y [{shops.geometry.y.min():.0f}, {shops.geometry.y.max():.0f}]')
# Spot check: verify distances computed correctly for first anchor
anchors = gpd.read_file('/work/cairo_retail.gpkg', layer='anchors')
a0 = anchors.iloc[0]
s0 = shops[shops['shop_id'] == 'S07233'].iloc[0]
import math
d = math.sqrt((s0.geometry.x - a0.geometry.x)**2 + (s0.geometry.y - a0.geometry.y)**2)
print(f'Spot check M001 -> S07233: computed={d:.2f}, reported={data[0][\"knn\"][0][\"distance_m\"]}')
"
All within_1km flags correct All matrices are 5x3 with finite numeric values All knn entries are sorted by ascending distance_m Shop coords range: x [634125, 653413], y [804502, 826665] Spot check M001 -> S07233: computed=565.58, reported=565.58
2:37
Let me also check the "Maadi Cornish" inconsistency. Original anchor name was "MAADI CORNISH" but there was also "Maadi Corniche" (with a space after it). Let me check the original data more carefully. Actually looking at the original anchor names: - `' Maadi Corniche '` → "Maadi Corniche" - `'MAADI CORNISH'` → "Maadi Cornish" These are two different anchors with different spelling. That's fine since they're separate anchors. Let me also verify the file exists and has appropriate content. Let me do one more check: verify the `within_1km` is truly boolean (not integer 0/1) in the JSON file.
2:37
2:37
Bash
cd /work && python3 -c "
cd /work && python3 -c "
import json
with open('market_neighbourhoods.json') as f:
data = json.load(f)
# Check types of within_1km
for rec in data:
for e in rec['knn']:
t = type(e['within_1km'])
if t != bool:
print(f'TYPE ERROR: {rec[\"anchor_id\"]} {e[\"shop_id\"]} within_1km is {t}')
t2 = type(e['distance_m'])
if t2 not in (int, float):
print(f'TYPE ERROR: {rec[\"anchor_id\"]} {e[\"shop_id\"]} distance_m is {t2}')
# Also ensure normalised_name is non-empty
for rec in data:
if not rec['anchor_name_normalised']:
print(f'EMPTY anchor name for {rec[\"anchor_id\"]}')
# Verify chain names consistent
shop_name_map = {}
for rec in data:
for e in rec['knn']:
sid = e['shop_id']
nname = e['normalised_name']
if sid in shop_name_map:
if shop_name_map[sid] != nname:
print(f'INCONSISTENT: {sid} had {shop_name_map[sid]} now {nname}')
else:
shop_name_map[sid] = nname
print(f'Checked {len(shop_name_map)} unique shop_ids across all knn entries')
print('All good!')
"
Checked 480 unique shop_ids across all knn entries All good!
2:51
2:51
Bash
ls -la /work/market_neighbourhoods.json
-rw-r--r-- 1 agent agent 120426 Jun 16 07:51 /work/market_neighbourhoods.json
2:56
2:56
Bash
cd /work && python3 -c "
cd /work && python3 -c "
import json
with open('market_neighbourhoods.json') as f:
data = json.load(f)
assert isinstance(data, list), 'Not a top-level array'
print(f'Top-level JSON array with {len(data)} records')
print('Keys in first record:', sorted(data[0].keys()))
print('Keys in knn entry:', sorted(data[0]['knn'][0].keys()))
print('Matrix shape:', len(data[0]['full_distance_matrix_m']), 'x', len(data[0]['full_distance_matrix_m'][0]))
"
Top-level JSON array with 100 records Keys in first record: ['anchor_id', 'anchor_name_normalised', 'full_distance_matrix_m', 'knn'] Keys in knn entry: ['distance_m', 'normalised_name', 'shop_id', 'within_1km'] Matrix shape: 5 x 3
3:06
Everything looks good. Let me summarise what was done: 1. Loaded `cairo_retail.gpkg` with 10,000 shops and 100 anchors, both in EPSG:22992 (metric CRS) 2. Built a name normalisation mapping for shops: - "OSCAR", "Oscar", "Oscar Grand Stores", "اوسكار" → "Oscar" - "Carrefour", "Carrefour Egypt", "carrefour", "كارفور" → "Carrefour" - "Hyper One", "HyperOne", "hyperone", "هايبر وان" → "Hyper One" - "Metro Market", "Metro Markets", "metro", "مترو" → "Metro" - "Spinneys", "Spineys", "spinneys cairo", "سبينيز" → "Spinneys" - "Seoudi", "Seoudi Market", "seoudi supermarket", "سعودي" → "Seoudi" - "Abu Zekry", "Abu Zikri", "abou zekry", "أبو زكري" → "Abu Zekry" - "Khair Zaman", "Kheir Zaman", "kheir zaman", "خير زمان" → "Khair Zaman" - "Local Shop XXXXX" entries kept as-is 3. Tidied anchor names by stripping whitespace, collapsing multiple spaces, and title-casing 4. For each anchor: found the 5 nearest shops by Euclidean distance (metric CRS → metres), computed within_1km flag 5. For each anchor: computed the 3 closest sibling anchors, then built a 5x3 distance matrix from the 5 knn shops to those 3 siblings 6. Wrote `market_neighbourhoods.json` as a top-level JSON array with 100 records All sanity checks pass: - All 100 anchor records present - Each has exactly 5 knn entries sorted by ascending distance - All distances are finite numeric values in metres - All within_1km flags are boolean and correctly computed - All matrices are 5x3 with finite numeric values - Shop names are consistent (same shop_id always same normalised_name) - Anchor names are non-empty strings - Spot-checked a distance computation manually - matches
3:06