Metodyka
Skąd bierzemy dane, co z nimi robimy i czego nie wiemy. Źródła, ograniczenia i cały pipeline krok po kroku.
Żabkozbiór to niezależny projekt fanowski/analityczny oparty na danych publicznych. Nie jest powiązany z Żabka Polska sp. z o.o. ani Żabka Group. Nazwa "Żabka" i powiązane znaki towarowe należą do ich właścicieli.
Źródła danych
Żabka – główne źródło
Lokalizacje sklepów pochodzą z publicznego pliku JSON na Żabka.pl - to ten sam plik, z którego korzysta sklepowa wyszukiwarka na ich stronie. Plik ma około 13 200 sklepów, każdy ze współrzędnymi GPS, adresem, godzinami otwarcia i flagami (piec Merrychef, otwarte w niedzielę, 24/7). Z pliku wyrzucamy dane osobowe dyrektorów, stałe pola (kraj, aktywność) i marketingowe URLe. Zostają same dane analityczne.
Podział administracyjny i mapowanie
Strukturę podziału terytorialnego Polski (trzy poziomy: województwa, powiaty i gminy) budujemy bezpośrednio z oficjalnych rejestrów GUS BDL oraz TERYT jako pierwszy krok procesu ETL. Sklepy oraz paczkomaty przypisujemy do tej hierarchii relacyjnie na podstawie ich nazw miejscowości, z wykorzystaniem oficjalnej Uniwersalnej Usługi Geokodowania GUGiK do jednoznacznego rozstrzygania przynależności mniejszych miejscowości i wsi, wraz z zapasowym dopasowaniem przestrzennym. Eliminuje to potrzebę stosowania uproszczonych plików GeoJSON i powolnych testów punkt-w-poligon.
Gospodarka – GUS BDL
Zarobki, bezrobocie i populacja na poziomie powiatów pochodzą z Banku Danych Lokalnych (zmienne 64428, 60270, 72305). Pobieramy je raz w roku. Nazwy powiatów trzeba normalizować – GUS lubi dodawać prefiksy (Powiat m.), przyrostki czasowe (od 2023) i zmieniać nazwy (jeleniogórski staje się karkonoski w 2021). Wszystko to czyścimy przed zmatchowaniem. Dokładność: dane pochodzą z roku, w którym GUS je opublikował, nie z bieżącego miesiąca.
Parki narodowe i krajobrazowe – GDOŚ
Granice parków i ich otulin pobieramy z WFS GDOŚ (warstwy ParkiNarodowe + ParkiKrajobrazowe). Mamy 259 obiektów: 0 parków narodowych z otulinami i 0 krajobrazowych. Każdy sklep sprawdzamy point-in-poligon. Jeśli trafił do parku lub otuliny, dostaje flagę.
Wysokość terenu – GUGiK NMT
Wysokość n.p.m. z Numerycznego Modelu Terenu GUGiK (GetHByXY, współrzędne PL-1992). Wyniki trafiają do lokalnego cache (elevation_cache.json) - ponowne odpalenie ETL nie odpytuje punktów, które już mamy. Uwaga: serwis GUGiK przyjmuje tylko współrzędne PL-1992, nie WGS84, więc w ETL jest konwersja własnym kodem (bez pyproj).
Paczkomaty InPost
Punkty paczkowe z publicznego API InPost ShipX (typ parcel_locker). Każdy paczkomat przypisujemy do podziału administracyjnego za pomocą tego samego geokodera GUGiK i relacyjnego dopasowania, co sklepy. To jest jednorazowe pobranie - sieć paczkomatów rośnie wolno, mamy około 31 950 punktów. Porównanie Żabek vs paczkomaty - z podziałem na województwa, powiaty i gminy - jest na dashboardzie.
Płazy – GBIF
Obserwacje płazów z Global Biodiversity Information Facility (klasa Amphibia, taxonKey=131) w Polsce. Mamy około 36 571 rekordów ze współrzędnymi. Za pomocą BallTree (haversine) zliczamy obserwacje w promieniu 5 km od każdego sklepu. Najbardziej żabia Żabka ma 2027 obserwacji - i to w Ursynowie, nie w żadnym parku narodowym.
Sąsiedztwo – obliczenia lokalne
Odległość do najbliższej innej Żabki obliczamy lokalnie przez BallTree (haversine, k=2). Najbardziej odosobniony sklep ma 27,3 km do najbliższego sąsiada (Michałowo, podlaskie). Punkt najdalszy od jakiejkolwiek Żabki - pusta przestrzeń w Bieszczady - to około 46,52 km. Czysta geometria na wczytanych już danych.
Pipeline ETL
Mamy codzienny proces ETL, który pobiera dane, czyści, wzbogaca i zapisuje do bazy. Wygląda tak:
- Pobranie. Pobieramy publiczny plik JSON z lokalizacjami sklepów. Jeśli API niedostępne, bierzemy z lokalnego pliku fallback z
data/input/. - Oczyszczenie. Deduplikacja po
storeId, normalizacja nazw miast, usuwanie<br>i kodów pocztowych z ulic, wyrzucenie danych osobowych i stałych pól. - Wzbogacenie. Każde źródło niezależnie: regiony, sąsiedztwo, płazy, parki, elewacja, GUS, paczkomaty. Błąd jednego źródła nie przerywa potoku - kolumna dostaje NULL i ETL idzie dalej. Każde zapytanie sieciowe ma retry 3 próby z odstępem 60s.
- Diff. Porównujemy z poprzednim snapshotem: nowe
store_idto sklep otwarty, zniknięte - zamknięty. Wynik zapisujemy jako historia zmian bezpośrednio w tabeli lokalizacji za pomocą pola deleted_at. - Zapis do bazy. Zapis do DuckDB. Nowe kolumny dodajemy przez
ALTER TABLE ADD COLUMN IF NOT EXISTS. - Czyszczenie cache. Po sukcesie ETL czyścimy cache Redis. Backend odbudowuje odpowiedzi na nowym stanie. Redis jest opcjonalny - jak niedostępny (np na srodowisku lokalnym), backend działa bez niego.
Czego nie gwarantujemy
Ograniczenia danych
- Około 204 sklepów nie ma daty otwarcia w źródłach – nie pojawiają się na wykresie historii wzrostu.
- Populacje powiatów to dane roczne z GUS, nie bieżące szacunki.
- Sklepy na granicach uproszczonych poligonów mogą trafić do sąsiedniego województwa (dotyczy około 3 punktów).
- Godziny otwarcia pochodzą ze źródła Żabki, nie z weryfikacji terenowej.
- Dane dot. lokalizacji Żabek obejmują jedynie aktualnie aktywne sklepy. Nie mamy więc danych historycznych - najstarsza Żabka niekoniecznie musi być najstarsza w ogóle, bo jest najstarsza z aktywnych.
- Obserwacje GBIF zależą od aktywności obserwatorów – mniej zamieszkałe regiony mają mniej rekordów nie dlatego, że jest mniej płazów, tylko dlatego, że mniej osób tam patrzy.
- Brakujące źródło wzbogacenia zostawia kolumnę NULL – tabela jest spójna, ale niekompletna.
- Soft delete: sklepy, które zniknęły ze źródła, dostają
deleted_atw bazie. Zapytania domyślnie filtrujądeleted_at IS NULL, więc zamknięte sklepy nie psują statystyk.