# Wczytaj trzy warstwy z GeoPackage (wygenerowane przez R/01_load_spatial.R)
# i od razu zrzutuj na PUWG-1992 (EPSG:2180) — w tym układzie odległości
# i powierzchnie są w metrach.
miasta <- sf::st_read(here::here("data", "processed", "miasta_padel.gpkg"),
quiet = TRUE) |>
sf::st_transform(EPSG_PUWG92)
wojewodztwa <- sf::st_read(here::here("data", "processed", "wojewodztwa.gpkg"),
quiet = TRUE) |>
sf::st_transform(EPSG_PUWG92)
drogi <- sf::st_read(here::here("data", "processed", "drogi.gpkg"),
quiet = TRUE) |>
sf::st_transform(EPSG_PUWG92)
# Granica Polski jako jeden multipoligon (st_union łączy wszystkie 16
# poligonów województw w jeden). Używamy potem do przycinania.
polska <- sf::st_union(wojewodztwa)
# OSM zwraca też odcinki dróg poza granicą kraju — st_intersection
# obcina je do Polski.
drogi <- sf::st_intersection(drogi, polska)
drogi <- drogi[sf::st_geometry_type(drogi) %in% c("LINESTRING", "MULTILINESTRING"), ]
# Upraszczamy geometrię dróg (próg 100 m) — mapa renderuje się szybciej
drogi_simpl <- drogi |>
sf::st_simplify(dTolerance = 100, preserveTopology = FALSE) |>
dplyr::group_by(typ) |>
dplyr::summarise(.groups = "drop")
Kluczowe operacje powyżej:
st_read(wczytanie GeoPackage) →st_transform(zmiana układu na PUWG-1992) →st_union(16 województw w 1 granicę Polski) →st_intersection(obcięcie dróg do granic kraju) →st_simplify(mniej wierzchołków = szybszy render).
Sprawozdanie analizuje przestrzenny rozkład klubów padlowych w Polsce w 2026 roku. W bazie znajduje się 40 klubów w 29 miastach, oferujących łącznie 147 kortów (średnio 3,7 kortu na klub). Analiza pokazuje, że oferta padlowa jest silnie skoncentrowana wokół metropolii — zwłaszcza Warszawy, Krakowa i Trójmiasta — natomiast wschodnie i północne województwa pozostają w znacznej mierze niedoreprezentowane.
Wykorzystaliśmy trzy typy danych przestrzennych (punkty, linie,
poligony), agregację atrybutów (aggregate()) oraz
tesselację Woronoja (st_voronoi).
Padel — sport rakietowy, w którym dwie pary zawodników rozgrywają mecz na zamkniętym korcie ze szklanymi ścianami — w ciągu ostatnich kilku lat przestał być w Polsce egzotyczną ciekawostką. Liczba kortów w Europie podwaja się w cyklu kilkuletnim, a w Polsce pierwsze obiekty komercyjne otwierano dopiero w drugiej dekadzie XXI wieku. Towarzyszy temu charakterystyczny problem nierówności geograficznej — kapitał i operatorzy koncentrują inwestycje w ośrodkach o wysokiej sile nabywczej.
Sprawozdanie pyta:
| Warstwa | Geometria | Liczba obiektów | Źródło | Plik w projekcie |
|---|---|---|---|---|
| Miasta z klubami padlowymi | punkty | 29 | ręczna lista miast (CSV) | data/processed/miasta_padel.gpkg |
| Drogi szybkiego ruchu | linie | 30061 | OpenStreetMap (motorway + trunk) | data/processed/drogi.gpkg |
| Województwa | poligony | 16 | GADM 4.1 level 1 | data/processed/wojewodztwa.gpkg |
Skąd wzięły się dane o klubach (warstwa punktów).
Ręcznie zweryfikowaliśmy listę 40 klubów padlowych w
29 polskich miastach (stan na 2026 r.) na podstawie
publicznych stron klubów oraz Map Google. Dla każdego miasta
zapisaliśmy: liczbę działających klubów, łączną liczbę kortów oraz
przybliżone współrzędne geograficzne miasta (centroid). Surowe dane:
data/raw/miasta_padel.csv.
Uwaga o precyzji. Punkty na mapach reprezentują miasta, nie konkretne adresy klubów. Dla analizy na skali kraju (1000+ km) jest to wystarczająca precyzja. Dla 5 klubów w Warszawie nie próbujemy ich rozróżnić przestrzennie — sumujemy je w jeden punkt z 27 kortami.
Skąd wzięły się granice województw (warstwa
poligonów). Pobrane z bazy GADM
4.1, poziom administracyjny 1 (województwa). Pakiet pobrany w
R/01_load_spatial.R, rozpakowany do
data/raw/gadm/, przekonwertowany na GeoPackage w
data/processed/wojewodztwa.gpkg.
Skąd wzięły się drogi szybkiego ruchu (warstwa
linii). Pobrane z OpenStreetMap przez Overpass
API za pomocą pakietu osmdata. Pobieramy dwa typy:
highway = motorway (autostrady) oraz
highway = trunk (drogi ekspresowe). Wynik zapisujemy w
data/processed/drogi.gpkg.
Układ współrzędnych. Wszystkie warstwy w
data/processed/ są w WGS84 (EPSG:4326). Przy wczytywaniu do
raportu od razu przerzucamy je na EPSG:2180 (PUWG-1992) — polski
państwowy układ, który zachowuje odległości w metrach na terenie Polski.
To pozwala poprawnie liczyć powierzchnie w km².
Mapa zbiera wszystkie trzy warstwy w jednym widoku: poligony województw jako tło, drogi szybkiego ruchu jako linie, miasta z klubami jako punkty (wielkość punktu odpowiada łącznej liczbie kortów w mieście).
Mapa 1. Miasta z klubami padlowymi (punkty), sieć dróg szybkiego ruchu (linie) i województwa (poligony).
Co widać? Trzy ośrodki dominujące — aglomeracja warszawska, Kraków i Trójmiasto — gromadzą większość kortów w kraju. Wzdłuż osi autostrady A2 (Poznań–Warszawa) widać korytarz inwestycji padlowych. Województwa wschodnie (lubelskie, podkarpackie, podlaskie) oraz zachodniopomorskie i lubuskie mają pojedyncze miasta z klubami.
Operacja aggregate() na obiekcie sf sumuje
atrybut (liczba_kortow) w obrębie każdego poligonu
(wojewodztwa). Wynikiem jest nowy obiekt sf, w
którym każde województwo ma policzoną sumę kortów wszystkich miast
leżących w jego granicach.
# aggregate.sf() to przestrzenny odpowiednik aggregate() z bazowego R:
# - bierze atrybut "liczba_kortow" z warstwy punktowej (miasta)
# - dla każdego poligonu z warstwy `by` (wojewodztwa) wybiera punkty,
# które w nim leżą (przestrzenne "group_by")
# - stosuje funkcję agregującą FUN (tu: sum)
# Wynik: nowy obiekt sf z geometrią województw + zsumowaną liczbą kortów.
korty_per_woj <- aggregate(
miasta["liczba_kortow"],
by = wojewodztwa,
FUN = sum,
na.rm = TRUE
)
# Województwa bez żadnego klubu: aggregate zwraca NA — zamieniamy na 0
korty_per_woj$liczba_kortow[is.na(korty_per_woj$liczba_kortow)] <- 0
# Dorzucamy nazwę województwa (aggregate gubi pozostałe kolumny,
# ale zachowuje kolejność wierszy)
korty_per_woj$wojewodztwo <- wojewodztwa$wojewodztwo
# Liczba miast z klubami na województwo — kolumna `wojewodztwo` jest już
# w danych (dodana przez st_join punkt → poligon przy generacji CSV).
liczba_miast <- miasta |>
sf::st_drop_geometry() |>
dplyr::group_by(wojewodztwo) |>
dplyr::summarise(liczba_miast = dplyr::n(), .groups = "drop")
Kluczowa operacja:
aggregate(miasta["liczba_kortow"], by = wojewodztwa, FUN = sum)— dla każdego województwa wybiera punkty (miasta) które w nim leżą i sumuje ich atrybutliczba_kortow. To jest przestrzenna agregacja wymagana przez prowadzącego.
Mapa 2. Łączna liczba kortów padlowych zsumowana w granicach każdego województwa (klasyfikacja Jenksa, 5 klas).
| Województwo | Miast z klubami | Kortów łącznie |
|---|---|---|
| Mazowieckie | 4 | 35 |
| Śląskie | 4 | 18 |
| Pomorskie | 4 | 15 |
| Małopolskie | 1 | 13 |
| Dolnośląskie | 1 | 12 |
| Łódzkie | 1 | 9 |
| Wielkopolskie | 1 | 9 |
| Kujawsko-Pomorskie | 2 | 6 |
| Zachodniopomorskie | 2 | 6 |
| Warmińsko-Mazurskie | 2 | 5 |
| Lubelskie | 1 | 4 |
| Lubuskie | 2 | 4 |
| Podkarpackie | 1 | 3 |
| Podlaskie | 1 | 3 |
| Świętokrzyskie | 1 | 3 |
| Opolskie | 1 | 2 |
Co widać? Na czele stoi województwo Mazowieckie (35 kortów w 4 miastach), co odzwierciedla skalę aglomeracji warszawskiej. Województwa z 0 kortów to obszary, które nie mają w bazie żadnego klubu padlowego — co potwierdza nierównomierność oferty.
Diagram Woronoja dzieli kraj na komórki — każdy punkt na mapie należy do tej komórki, której centralny punkt (klub) leży najbliżej. Wielkość komórki to bezpośrednia miara strefy oddziaływania klubu: duża komórka oznacza, że alternatywny klub jest daleko.
# Krok 1: st_voronoi działa na pojedynczej geometrii (jeden MULTIPOINT),
# więc najpierw scalamy 29 osobnych punktów w jeden obiekt.
miasta_mp <- sf::st_union(miasta)
# Krok 2: Właściwa tesselacja — zwraca obiekt typu GEOMETRYCOLLECTION
# zawierający komórki Woronoja jako poligony.
voronoi_raw <- sf::st_voronoi(miasta_mp)
# Krok 3: Wyciągamy z geometrycollection same poligony i opakowujemy
# w obiekt sf (żeby móc je rysować i robić joiny).
voronoi_polys <- sf::st_collection_extract(voronoi_raw, "POLYGON")
voronoi_sf <- sf::st_sf(geom = voronoi_polys, crs = sf::st_crs(miasta))
# Krok 4: Każdej komórce przypisujemy atrybuty miasta, które w niej leży
# (st_contains: dla każdej komórki znajdź punkt-miasto wewnątrz).
voronoi_sf <- sf::st_join(voronoi_sf, miasta, join = sf::st_contains)
# Krok 5: st_voronoi rysuje komórki w nieskończoność (po bbox punktów) —
# obcinamy je do granic Polski przez st_intersection.
voronoi_pl <- sf::st_intersection(voronoi_sf, polska)
# Krok 6: Powierzchnia każdej komórki w km² (st_area w PUWG zwraca m²,
# units::set_units konwertuje na km²).
voronoi_pl$pow_km2 <- as.numeric(
sf::st_area(voronoi_pl) |> units::set_units("km^2")
)
sr_pow <- round(mean(voronoi_pl$pow_km2, na.rm = TRUE), 0)
max_pow <- round(max(voronoi_pl$pow_km2, na.rm = TRUE), 0)
Kluczowe operacje:
st_union(scal punkty) →st_voronoi(tesselacja) →st_collection_extract(wybierz POLYGON) →st_join(komórka ← miasto) →st_intersection(obetnij do Polski) →st_area+set_units("km^2")(powierzchnia).
Mapa 3. Tesselacja Woronoja — kraj podzielony na rejony najbliższego miasta z klubem padlowym. Kolor odpowiada powierzchni komórki w km².
Co widać? Średnia powierzchnia rejonu to 10 765 km², ale największa komórka ma aż 25 213 km² — to pojedyncze miasto obsługujące dużą część Polski wschodniej lub północnej. Duże (ciemne) komórki tworzą charakterystyczny pas od Pomorza Środkowego, przez Warmię i Podlasie, do Lubelszczyzny i Bieszczad. Małe komórki w okolicach Warszawy, Krakowa i Trójmiasta odpowiadają wysycaniu rynku w aglomeracjach.
Koncentracja w aglomeracjach. Trzy województwa (Mazowieckie, Śląskie, Pomorskie) gromadzą 46% wszystkich kortów w kraju.
Padel-pustynie. Tesselacja Woronoja pokazuje regiony, w których pojedyncze miasto obsługuje obszar znacznie większy niż średni (10 765 km²) — Warmia, Podlasie, Bieszczady.
Korytarze inwestycyjne. Mapa 1 ujawnia, że miasta z klubami padlowymi układają się wzdłuż głównych autostrad (A2, A4) — co sugeruje, że operatorzy lokalizują kluby tam, gdzie jest infrastruktura transportowa obsługująca największą bazę klientów.
osmdata. https://www.openstreetmap.org