Pre izvesnog vremena smo uzeli Mladenovac i izmapirali sve kuće u njemu. Postavilo se pitanje koju bismo sledeću opštinu mogli da mapiramo. Bilo je logično uzeti neku gde je mapiranost zgrada najgora, ali kako to naći?
U ovom postu ću pričati malo kako provaliti gde je mapiranost mala, kako Python-om procesirati geojson i Shapefile-ove i pokušati da dođem do odgovora na pitanje koja je opština u Srbiji najgore mapirana.
Šac metoda
Najprostiji i najočigledniji način je da se ode na sajt disaster.ninja, da se odabere odnos zgrada i naseljenosti i da se vidi „šac” metodom šta će da ispadne. Evo kako izgleda cela Srbija (primetiti kako se Mladenovac zeleni😀):
Nažalost, „šac” metoda se razlikuje od nivoa zuma i neki gradovi deluju loše mapirani, ali onda zumiraš i vidiš da se ipak donekle OK urađeni. Evo npr. kako izgleda Jagodina iz daljine i kada se zumira:
Daleko da je savršena, ali vide se zeleni (mapirani) delovi. To nije ni blizu kao kad se pogleda Mladenovac, gde kada smo počeli da ga radimo, bilo je ukupno 2 (slovima: dve) zgrade na celoj opštini.
Obilazeći Srbiju ovako na ovom sajtu dolazimo do sledećih „kandidata”:
- Grad Sombor (ne cela opština)
- Opština Bosilegrad
- Opština Osečina
- Opština Bela Crkva
- Opština Despotovac
- Opština Ćićevac
- Opština Surdulica
- Naselje Bečej
Da li su ovo najbolji kandidati ili ne – teško je reći. Ali zato možemo da koristimo analitiku😉.
Analitika
Evo šta mi je palo na pamet. Ovaj disaster.ninja prikazuje odnos zgrada iz OSM-a i gustine naseljenosti i to po nekim šestaugaonicima, ali još bolje bi bilo da možemo da imamo odnos stvarnog broja zgrada i zgrada iz OSM-a, i to po opštinama – tako bi znali koliko i gde još stvarno fali. Međutim, nemamo prave zgrade (da imamo – problem možda ne bi ni postojao😀), ali imamo nešto što je možda blizu tome, a to su zgrade koje je izgenerisao Microsoft uz pomoć mašinskog učenja i dao na otvoreno i besplatno korišćenje. Zvaćemo ih ML zgrade na dalje. Koji mi je plan – 1. uzmemo zgrade iz OSM-a, 2. uzmemo ove ML zgrade, 3. nađemo njihov odnos za svaku opštinu, sortiramo to od najboljeg do najgoreg i tako nađemo sledeću opštinu za mapiranje! Ako vas ne zanima programiranje, preskočite na deo „Rezultati” da vidite šta se dobija.
Da se bacimo na posao – od sastojaka nam trebaju:
- ML zgrade koje uzmemo odavde (nađite Srbiju tu i skinućete ZIP u kome su zgrade u „geojsonl” formatu),
- OSM zgrade ćemo da uzmemo odavde (skinite .shp.zip u kome je jedan od Shapefile-ova sa zgradama iz OSM-a),
- Administrativne granice koje je najlakše skinuti odavde (kliknite „Download” i odaberite Srbiju sa svim granicama od nivoa 2 do 9 i dobićete geojson sa svim granicama)
Šta nam sad treba – da otvorimo ovaj geojson sa granicama (iz poslednjeg koraka) i da dodamo nove kolone, npr. „osm_buildings” i „ml_buildings” u kojima ćemo da upišemo koliko smo zgrada našli za svaku opštinu. Da otvorimo zgrade, dovoljno je u Python-u da uradimo ovo:
1 2 | import geopandas as gpd boundaries = gpd.read_file('serbia-boundaries.geojson') |
Tako dobijamo sve granice u GeoPandas data frame-e. Da bismo otvorili Shapefile sa OSM zgradama, koristićemo Fiona biblioteku.
1 2 | import fiona osm_buildings = fiona.open("gis_osm_buildings_a_free_1.shp", "r") |
E, sad iteriramo za svaku OSM zgradu i nađemo sve preseke sa administrativnim granicama koje smo uzeli kao u prethodnom koraku (hoćemo da dobijemo sva naselja i opštine koje zgrada geometrijski seče). GeoPandas ima podršku za preseke geometrija, pa ni ovo nije teško:
1 2 3 4 5 | from shapely.geometry import shape for osm_building in osm_buildings: building_shape = shape(osm_building['geometry']) filtered_boundaries = boundaries.sindex.query(building_shape, predicate='intersects') |
Primetite da moramo da konvertujemo ulaznu zgradu u „shape”, i da koristimo „sindex” (tj. „spatial index” da bismo ubrzali operaciju presecanja zgrade sa granicama). E, sad, operacija „query” vraća indekse granica (tj. indekse pozicija tih objekata u data frame-u). Tehnički, mogli bismo da odmah napravimo novu kolonu „osm_buildings” i da to odmah vraćamo nazad u data frame tako što inkrementiramo tu kolonu na indeksu svake presečene zgrade, ali bi to bilo jako sporo, pa sam se odlučio da sve te vraćene indekse čuvam u privremenom dictionary-ju (običnom Python) koji ćemo tek na kraju da prebacimo u data frame:
1 2 | for idx in filtered_boundaries: counter[idx] += 1 |
A na kraju uradimo ovako nešto i snimimo novi geojson:
1 2 3 | import pandas as pd boundaries['osm_buildings'] = pd.Series(counter) boundaries.to_file('boundaries_with_osm.geojson', driver='GeoJSON', encoding='utf-8') |
Što se tiče ML zgrada, situacija je slična – iteriramo za sve zgrade i dodamo ih kao novu kolonu. Razlika je ovog puta što čitamo „geojsonl” format (to je geojson gde je jedan objekat u jednoj liniji u fajlu) i što je fajl oooogroman, pa sam odlučio da ne koristim ove fensi Python biblioteke (GeoPandas) jer su još nezrele i ne mogu da strimuju fajl, nego moraju da ga učitaju celog, a ove ML zgrade su ogromne i ovo ne bi radilo ko nema par gigabajta RAM-a. Iskoristio sam činjenicu da je samo jedna zgrada u liniji ulaznog fajla i čitao sam onda liniju po liniju (najgluplje moguće, na standardni Python način) i tako obrađivao zgrade. Sve u svemu, ceo kod izgleda nekako ovako:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | import geopandas as gpd import pandas as pd import fiona import json from shapely.geometry import shape def append_ml_buildings(boundaries): counter = {} for idx in boundaries.index: counter[idx] = 0 with open('serbia-ml-buildings.geojsonl', 'r') as building_file: for line in building_file: building_shape = shape(json.loads(line)['geometry']) filtered_boundaries = boundaries.sindex.query(building_shape, predicate='intersects') for idx in filtered_boundaries: counter[idx] += 1 return counter def append_osm_buildings(boundaries): counter = {} for idx in boundaries.index: counter[idx] = 0 with fiona.open("gis_osm_buildings_a_free_1.shp", "r") as osm_buildings: for osm_building in osm_buildings: building_shape = shape(osm_building['geometry']) filtered_boundaries = boundaries.sindex.query(building_shape, predicate='intersects') for idx in filtered_boundaries: counter[idx] += 1 return counter def main(): boundaries = gpd.read_file('serbia-boundaries.geojson') _ = boundaries.sindex counter = append_ml_buildings(boundaries) boundaries['ml_buildings'] = pd.Series(counter) counter = append_osm_buildings(boundaries) boundaries['osm_buildings'] = pd.Series(counter) boundaries.to_file('output.geojson', driver='GeoJSON', encoding='utf-8') if __name__ == '__main__': main() |
Rezultati
Interesantno, ali neki delovi Srbije uopšte nisu imali ML zgrade – celo Trgovište, jedan deo oko Pirota i jedan mali deo posle Priboja na tromeđi sa BiH i Crnom Gorom. Tamo definitivno ima zgrada na satelitskim snimcima, tako da ne znam šta je posredi. Ako uzmemo odnos OSM i ML zgrada i probamo da iscrtamo sva naselja („admin_level=9” u OSM terminologiji), dobijamo ovakvu situaciju (klik na veću sliku):
Ovo je dosta nepregledno jer gledamo jako sitne teritorije, ali mogu da se primete neke stvari. Beograd i Užice su sjajni, Vojvodina ne zaostaje mnogo, kao ni delovi oko većih gradova. Ali – mi gledamo da mapiramo teritoriju slične veličine kao opština Mladenovac, pa je onda logičnije da gledamo opštine („admin_level=8” u OSM terminologiji) i gradove, a ne naselja. Kada to vizuelizujemo, dobijamo ovako nešto (klik za veću sliku):
Kad sam radio ovu sliku, bio sam malo mudriji, pa sam stavio i „100+ %” jer ima mesta gde je broj zgrada u OSM-u veći nego broj ML zgrada (što je skroz OK i legitimno). Opet se vidi kako Mladenovac dominira, ali se vidi i par „rupa”. Ali koja je rupa najgora? Na kraju je data cela tabela sa svim opštinama, pa analizirajte! Par mojih komentara:
- Rača je nešto manja od Mladenovca, nema velikih gradova i deluje kao dobar kandidat
- Ovi moji kandidati dobijeni „šac” metodom (Sombor, Bosilegrad…) nisu ni u prvih 10 (osim Ćićevca), toliko o šac metodama😀
- U moju, i u odbranu svih šac metoda – ja sam prirodno po sajtu disaster.ninja gledao veće gradove, pa su mi oni bili na vrhu, tako da mi je analiza bila nagnuta (engl. biased) na tu stranu. Ovde su uglavnom pri vrhu opštine koje nemaju baš velike gradove u svojoj blizini (jer opštine sa velikim gradovima obično imaju nešto bar mapirano), tako da je i ova analiza nagnuta na drugu stranu. Možda nije loše ni tako odabrati opštinu!
- Kad smo kod toga i kod „impakta” – prema Vikiju, Mladenovac ima 50,000 duša, Rača 10,000, a Sombor 80,000, tako da bi definitivno bilo i teže i veći impakt da se odradi Sombor.
- Sve vizuelizacije lažu, pa tako i ova iznad. Kada je čovek vidi, pomisli da je Srbija relativno dobro mapirana, ali to je samo zato što sam tako odabrao granice opsega. Da su mi granice opsega bile zaokružene (0-20%, 20-40%…), otkrila bi se mnogo realnija situacija izmapiranosti zgrada u Srbiji, ovako nešto:
Još jedan pokazatelj kako sa podacima i vizuelizacijama može da se manipuliše ljudima.
Na kraju dana, treba odabrati:
- Sombor – slične površine kao Mladenovac, sa više stanovnika, veći impakt, ali teže će ga biti završiti. Nije centralna Srbija, pa posle Mladenovca malo šaramo i u Vojvodini.
- Kikinda – manje stanovnika nego Sombor, ali isto u Vojvodini, a najgore mapiran grad u Vojvodini
- Jagodina – najgore mapiran grad na nivou cele Srbije
- Rača – mala opština, najmanji apsolutni odnos izmapiranih zgrada u Srbiji, manji impakt, ali možemo je relativno brzo završiti.
Na kraju, evo tabele svih ML i OSM zgrada za sve opštine:
Општина/град | Број ML зграда | Број OSM зграда | OSM / ML |
---|---|---|---|
Општина Рача | 15461 | 11 | 0,07% |
Општина Бојник | 14279 | 15 | 0,10% |
Општина Коцељева | 20921 | 33 | 0,15% |
Општина Ћићевац | 10821 | 30 | 0,27% |
Општина Житорађа | 18058 | 54 | 0,29% |
Општина Дољевац | 14937 | 50 | 0,33% |
Општина Кучево | 23193 | 80 | 0,34% |
Општина Лајковац | 22199 | 79 | 0,35% |
Општина Жабари | 18884 | 76 | 0,40% |
Општина Ражањ | 13325 | 54 | 0,40% |
Општина Александровац | 24269 | 113 | 0,46% |
Општина Мерошина | 14632 | 85 | 0,58% |
Општина Нова Црња | 11205 | 73 | 0,65% |
Општина Жабаљ | 21724 | 152 | 0,69% |
Општина Кула | 30774 | 223 | 0,72% |
Општина Тутин | 22759 | 165 | 0,72% |
Општина Љиг | 22546 | 164 | 0,72% |
Општина Ковачица | 19422 | 149 | 0,76% |
Град Јагодина | 48273 | 424 | 0,87% |
Општина Смедеревска Паланка | 42679 | 388 | 0,90% |
Општина Чока | 12348 | 116 | 0,93% |
Општина Рековац | 19441 | 206 | 1,05% |
Општина Сврљиг | 16614 | 178 | 1,07% |
Општина Велика Плана | 38496 | 427 | 1,10% |
Општина Варварин | 19239 | 215 | 1,11% |
Општина Деспотовац | 25667 | 289 | 1,12% |
Општина Лебане | 22671 | 259 | 1,14% |
Општина Врбас | 24589 | 336 | 1,36% |
Општина Мионица | 26732 | 375 | 1,40% |
Општина Лучани | 35600 | 509 | 1,42% |
Општина Бачка Паланка | 38044 | 577 | 1,51% |
Општина Сурдулица | 15442 | 240 | 1,55% |
Општина Голубац | 10983 | 181 | 1,64% |
Општина Лапово | 7840 | 131 | 1,67% |
Општина Апатин | 18579 | 312 | 1,67% |
Општина Ариље | 24131 | 409 | 1,69% |
Општина Мали Иђош | 11027 | 190 | 1,72% |
Општина Брус | 18405 | 326 | 1,77% |
Општина Уб | 49290 | 900 | 1,82% |
Општина Ивањица | 36773 | 675 | 1,83% |
Општина Ковин | 27424 | 538 | 1,96% |
Општина Аранђеловац | 39340 | 797 | 2,02% |
Општина Ада | 16764 | 366 | 2,18% |
Општина Жагубица | 19233 | 431 | 2,24% |
Општина Сјеница | 25620 | 576 | 2,24% |
Општина Осечина | 21213 | 548 | 2,58% |
Општина Нова Варош | 20888 | 550 | 2,63% |
Општина Ириг | 11237 | 309 | 2,74% |
Општина Топола | 27674 | 769 | 2,77% |
Град Краљево | 104274 | 2972 | 2,85% |
Град Зајечар | 53790 | 1546 | 2,87% |
Град Смедерево | 62633 | 1818 | 2,90% |
Општина Власотинце | 24179 | 714 | 2,95% |
Општина Кнић | 29722 | 882 | 2,96% |
Градска општина Костолац | 8983 | 289 | 3,21% |
Општина Босилеград | 1612 | 52 | 3,22% |
Општина Владичин Хан | 16454 | 543 | 3,30% |
Градска општина Лазаревац | 55278 | 1862 | 3,36% |
Град Чачак | 95245 | 3319 | 3,48% |
Општина Бач | 13269 | 475 | 3,57% |
Општина Пожега | 37433 | 1366 | 3,64% |
Град Ваљево | 79125 | 2896 | 3,66% |
Град Лозница | 63744 | 2449 | 3,84% |
Општина Баточина | 13847 | 532 | 3,84% |
Општина Сечањ | 14594 | 572 | 3,91% |
Градска општина Сопот | 27771 | 1116 | 4,01% |
Град Крушевац | 76626 | 3184 | 4,15% |
Град Кикинда | 36490 | 1624 | 4,45% |
Градска општина Пожаревац | 45223 | 2023 | 4,47% |
Општина Књажевац | 32151 | 1441 | 4,48% |
Општина Бачки Петровац | 12565 | 604 | 4,80% |
Градска општина Црвени Крст | 21779 | 1083 | 4,97% |
Општина Врњачка Бања | 22988 | 1147 | 4,98% |
Град Сомбор | 60477 | 3018 | 4,99% |
Општина Трстеник | 36988 | 1887 | 5,10% |
Општина Шид | 27664 | 1456 | 5,26% |
Општина Бечеј | 30881 | 1678 | 5,43% |
Општина Сокобања | 16336 | 929 | 5,68% |
Општина Велико Градиште | 20853 | 1210 | 5,80% |
Општина Бела Црква | 14407 | 837 | 5,80% |
Град Вршац | 29703 | 1747 | 5,88% |
Општина Горњи Милановац | 54773 | 3227 | 5,89% |
Општина Крупањ | 16397 | 973 | 5,93% |
Општина Алибунар | 21742 | 1311 | 6,02% |
Градска општина Врање | 12734 | 800 | 6,28% |
Општина Љубовија | 16179 | 1020 | 6,30% |
Општина Владимирци | 29185 | 1868 | 6,40% |
Град Крагујевац | 94337 | 6299 | 6,67% |
Општина Прешево | 15095 | 1008 | 6,67% |
Град Лесковац | 95036 | 6550 | 6,89% |
Општина Петровац на Млави | 40967 | 2837 | 6,92% |
Општина Беочин | 12336 | 870 | 7,05% |
Општина Темерин | 18428 | 1395 | 7,57% |
Општина Алексинац | 49817 | 3799 | 7,62% |
Град Нови Пазар | 43703 | 3439 | 7,86% |
Општина Гаџин Хан | 13908 | 1109 | 7,97% |
Општина Пландиште | 12636 | 1023 | 8,09% |
Градска општина Врањска Бања | 4504 | 365 | 8,10% |
Општина Неготин | 41706 | 3416 | 8,19% |
Општина Нови Бечеј | 19002 | 1574 | 8,28% |
Општина Мајданпек | 14111 | 1170 | 8,29% |
Општина Свилајнац | 31273 | 2612 | 8,35% |
Општина Житиште | 18589 | 1611 | 8,66% |
Општина Медвеђа | 11406 | 993 | 8,70% |
Општина Бољевац | 18933 | 1650 | 8,71% |
Општина Мало Црниће | 17269 | 1528 | 8,84% |
Општина Пријепоље | 27900 | 2701 | 9,68% |
Општина Рума | 38161 | 3757 | 9,84% |
Општина Кладово | 22083 | 2300 | 10,41% |
Општина Оџаци | 22436 | 2362 | 10,52% |
Општина Рашка | 27793 | 2958 | 10,64% |
Општина Тител | 12034 | 1342 | 11,15% |
Општина Бујановац | 16298 | 1826 | 11,20% |
Општина Кањижа | 22467 | 2631 | 11,71% |
Општина Опово | 7002 | 918 | 13,11% |
Општина Бабушница | 15324 | 2069 | 13,50% |
Град Шабац | 92294 | 12547 | 13,59% |
Општина Црна Трава | 3621 | 494 | 13,64% |
Општина Блаце | 17403 | 2418 | 13,89% |
Општина Бачка Топола | 26075 | 3675 | 14,09% |
Град Прокупље | 38817 | 5807 | 14,95% |
Градска општина Нишка Бања | 11000 | 1815 | 16,5% |
Општина Димитровград | 10470 | 1752 | 16,73% |
Општина Инђија | 36600 | 6681 | 18,25% |
Општина Мали Зворник | 8295 | 1516 | 18,27% |
Општина Прибој | 12979 | 2450 | 18,87% |
Општина Параћин | 42978 | 8388 | 19,51% |
Општина Чајетина | 25752 | 5272 | 20,47% |
Градска општина Палилула | 27799 | 5841 | 21,01% |
Градска општина Гроцка | 51709 | 11733 | 22,69% |
Градска општина Пантелеј | 17526 | 4011 | 22,88% |
Општина Ћуприја | 24607 | 5991 | 24,34% |
Град Сремска Митровица | 54085 | 13695 | 25,32% |
Градска општина Обреновац | 59256 | 15930 | 26,88% |
Општина Косјерић | 20235 | 5829 | 28,80% |
Општина Сремски Карловци | 4871 | 1442 | 29,60% |
Град Зрењанин | 73731 | 23164 | 31,41% |
Општина Куршумлија | 23348 | 7707 | 33,00% |
Град Нови Сад | 94931 | 34818 | 36,67% |
Општина Богатић | 35573 | 14870 | 41,80% |
Град Суботица | 90836 | 40402 | 44,47% |
Град Бор | 29318 | 13063 | 44,55% |
Општина Србобран | 14359 | 8033 | 55,94% |
Градска општина Вождовац | 36437 | 21331 | 58,54% |
Градска општина Чукарица | 36606 | 22746 | 62,13% |
Општина Нови Кнежевац | 9416 | 6323 | 67,15% |
Општина Бела Паланка | 14372 | 9703 | 67,51% |
Градска општина Барајево | 31560 | 22909 | 72,58% |
Град Панчево | 56491 | 45464 | 80,48% |
Градска општина Ужице | 48543 | 40284 | 82,98% |
Градска општина Медијана | 8078 | 6730 | 83,31% |
Градска општина Палилула | 40876 | 35421 | 86,65% |
Градска општина Раковица | 11814 | 10754 | 91,02% |
Општина Бајина Башта | 31698 | 29320 | 92,49% |
Градска општина Младеновац | 39477 | 36893 | 93,45% |
Градска општина Сурчин | 31127 | 30000 | 96,37% |
Градска општина Земун | 41372 | 40126 | 96,98% |
Општина Сента | 18046 | 17846 | 98,89% |
Градска општина Савски венац | 5098 | 5115 | 100,33% |
Градска општина Нови Београд | 10135 | 10523 | 103,82% |
Градска општина Севојно | 4157 | 4754 | 114,36% |
Општина Пећинци | 19834 | 23155 | 116,74% |
Градска општина Звездара | 19338 | 23023 | 119,05% |
Општина Стара Пазова | 41011 | 52907 | 129,00% |
Градска општина Врачар | 2711 | 4301 | 158,64% |
Градска општина Стари град | 1712 | 3092 | 180,60% |
Град Пирот | 8270 | 18188 | Непознато |
Општина Трговиште | 0 | 558 | Непознато |