Ceny mieszkań do wynajęcia
Znacie to nagranie?
- No, ja mam M1 do wynajęcia…
- To już nie jest aktualne, wie pan?
Pytanie brzmi za ile wynająć takie M1? Albo ile zapłacić? W zależności od lokalizacji.
Skąd wziąć dane?
Sprawdzimy jakie są rynkowe ceny najmu mieszkań, korzystając jak zwykle z dostępnych źródeł. Popatrzymy globalnie, na cały kraj. Popatrzymy też statystycznie (bez dużej ingerencji w dane)., a skoro statystycznie to potrzebujemy dużo danych, żeby statystyka miała sens. Tym bardziej że będziemy głównie uśredniać (albo precyzyjniej - opierać się na medianach, czyli wartościach środkowych). Skąd weźmiemy dane? Z serwisów ogłoszeniowych. Jest kilka specjalizujących się w nieruchomościach (np. otodom.pl), ale są też inne gdzie przewija się znacznie więcej ogłoszeń - OLX.pl, gumtree.pl czy gratka.pl. Ta ostatnia okazała się najbardziej przydatna. Z prostego powodu - na liście wyników wyszukiwania znajdujemy potrzebne dane (dzięki temu wystarczy przeskanować kolejne strony indeksu zamiast wchodzić na każde ogłoszenie - jest szybciej), ułożone dodatkowo w sensownym HTMLu. Jeśli chcesz pominąć technikalia - skroluj dalej, albo kliknij sobie tutaj i przejdź do analizy, a jeśli interesują Cię ceny mieszkań w Warszawie - to też jest, a nieco dalej w innych miastach. Już możecie się domyślić, że metodą “czołgową” przejedziemy po kolei wszystkie strony i sobie pobierzemy to co nam potrzebne. Potrzebujemy kilku bibliotek, przy okazji zdefiniujemy “standardowy” wygląd wszystkich wykresów (żeby nie dodawać za każdym razem moje ulubione “+ theme_minimal()”).
library(rvest)
library(dplyr)
library(tidyr)
library(ggplot2)
library(stringr)
# wygląd wykresów dla wszystkich
theme_set(theme_minimal())
Początek dość oczywisty, pobranie danych w sumie też. Ale to jest najbardziej żmudna część pracy.
Pobranie danych
Jak zrobić to metodycznie?
- Wchodzimy na wybrany serwis, szukamy tego, co będziemy pobierać (w tym przypadku mieszkania do wynajęcia, dodatkowo z kilkoma parametrami, które sprawią że w wynikach dostaniemy stosunkowo kompletne dane).
- Patrzymy jak wyglądają linki do wygenerowanych stron
- Sprawdzamy ile jest tych stron (w tym przypadku wyszło mi 1043)
- Sprawdzamy kilka kolejnych stron - jak zmienia się link?
- Oglądamy dokładnie HTMLa, najlepiej i najwygodniej przy użyciu jakiejś wtyczki typu WebDeveloper czy po prostu “Zbadaj” w Chrome
Jak to wszystko wiemy - krok o kroku próbujemy wyłuskać poszczególne pola ze strony. Próbujemy z jednym polem (np. cena mieszkania) - sprawdzamy na stronie czy otrzymane wyniki są zgodne z tym co “wyłuskaliśmy”. Potem z drugim polem. I tak do końca. Dla Gratki na obecną chwilę (do HTML może się zmienić ze zmianami w serwisie) działający kod wygląda tak:
## pobranie danych
url_pre <- "https://dom.gratka.pl/mieszkania-do-wynajecia/lista/,,1,40,"
url_post <- ",1,1,co,li,s,mo,lpo.html"
oferty <- data.frame(stringsAsFactors = F)
for(i in 1:1043) {
url <- paste0(url_pre, i, url_post)
page <- read_html(url) %>%
html_node("div.wrapper") %>%
html_node("div#ogloszenia") %>%
html_node("div.small-12") %>%
html_node("ul#list-ads") %>%
html_nodes("li.ogloszenie")
# ceny
cena <- page %>%
html_node("div.detailedPrice") %>%
html_node("p") %>%
html_node("b") %>%
html_text() %>%
gsub(" ", "", .) %>%
as.numeric()
# lokalizacje
lokalizacja <- page %>%
html_nodes("div.ogloszenieInfo") %>%
html_node("h2") %>%
html_text()
tmp <- page %>%
html_nodes("div.ogloszenieInfo") %>%
html_node("div.infoLista") %>%
html_node("p.infoDane")
liczba_pokoi <- tmp %>%
html_text() %>%
strsplit(split = ",") %>%
do.call(rbind, .) %>%
.[,1]
powierzchnia <- tmp %>%
html_nodes("span") %>%
html_nodes("b") %>%
html_text() %>%
gsub(",", ".", .) %>%
as.numeric()
pietro <- tmp %>%
html_text() %>%
strsplit(split = ",") %>%
do.call(rbind, .) %>%
.[,2]
oferty <- rbind(oferty,
data.frame(lokalizacja, cena,
powierzchnia, liczba_pokoi, pietro,
stringsAsFactors = F))
}
Po pobraniu danych czas na drugą kwestię typu “pain in the ass”, czyli
czyszczenie danych
i ewentualne dodanie wartości wyliczonych na potrzeby dalszych analiz. Rozdzielimy na początek pole z lokalizacją na miasto, dzielnicę i ulicę (z której akurat tutaj nie będziemy korzystać - ale można użyć kombinacji miasto-ulica do zaznaczenia punktów (ogłoszeń) na mapie, korzystając z GoogleMaps).
oferty <- separate(oferty, lokalizacja,
into=c("miasto", "ulica"),
sep =",")
oferty$miasto <- gsub("Mieszkanie ", "", oferty$miasto)
oferty$dzielnica <- substr(oferty$miasto,
lapply(oferty$miasto,
function(x) as.numeric(str_locate(x, " ")[2])+1), nchar(oferty$miasto))
oferty$miasto <- substr(oferty$miasto, 1, lapply(oferty$miasto,
function(x) as.numeric(str_locate(x, " ")[1])-1))
# wybieramy tylko potrzebne kolumny
oferty <- oferty[,c(1,7,2,3,4,5,6)]
# dodajemy średnią cenę za metr kwadratowy
oferty$cena_za_metr <- oferty$cena / oferty$powierzchnia
# usuwamy braki
oferty <- na.omit(oferty)
# tylko do 6 pokoi
oferty$liczba_pokoi <- gsub("\\W", " ", oferty$liczba_pokoi)
oferty <- filter(oferty,
liczba_pokoi %in% c("1 pokój", "2 pokoje", "3 pokoje",
"4 pokoje", "5 pokoi", "6 pokoi"))
oferty$liczba_pokoi <- factor(oferty$liczba_pokoi,
levels = c("1 pokój", "2 pokoje", "3 pokoje",
"4 pokoje", "5 pokoi", "6 pokoi"))
Uff… tyle na temat pobierania. Na dzień dobry mamy 28023 oferty. Liczba ofert w poszczególnych miastach wygląda następująco (długa tabela):
| miasto | n |
|---|---|
| Warszawa | 14422 |
| Kraków | 4998 |
| Katowice | 1528 |
| Poznań | 1364 |
| Łódź | 1134 |
| Wrocław | 1104 |
| Gdańsk | 807 |
| Szczecin | 440 |
| Lublin | 352 |
| Gdynia | 298 |
| Toruń | 278 |
| Gliwice | 256 |
| Rzeszów | 158 |
| Sopot | 155 |
| Kielce | 98 |
| Olsztyn | 83 |
| Dąbrowa | 80 |
| Sosnowiec | 67 |
| Bydgoszcz | 46 |
| Białystok | 38 |
| Zabrze | 30 |
| Chorzów | 26 |
| Będzin | 23 |
| Tychy | 22 |
| Częstochowa | 19 |
| Opole | 18 |
| Wałbrzych | 16 |
| Bielsko-Biała | 14 |
| Słupsk | 14 |
| Mińsk | 12 |
| Nowy | 12 |
| Tarnowskie | 11 |
| Bytom | 10 |
| Mysłowice | 10 |
| Zielona | 10 |
| Bielany | 8 |
| Pruszków | 8 |
| Tarnów | 8 |
| Gniezno | 7 |
| Piotrków | 7 |
| Tczew | 7 |
| Jaworzno | 6 |
| Pruszcz | 6 |
| Ruda | 6 |
| Siemianowice | 4 |
| Świętochłowice | 3 |
Trochę za dużo, ostatnie miasta na liście mają po kilka ogłoszeń - może zepsuć nam to statystykę.
Ograniczenie ilości danych
Zostawimy więc tylko miasta z dużą ilością ofert (więcej niż trzeci kwartyl). Dodatkowo odrzucamy skrajne 5% cen za metr (za dużo i za mało) - po przeglądzie danych w tabeli oferty widać tam ewidentne błędy użytkowników, które na szybko można podzielić na dwa typy:
- mieszkania w cenie kilkuset tysięcy - to raczej sprzedaż niż wynajem
- jakieś minimalne ceny - podejrzewam że może chodzić o wynajęcie jednego pokoju za kilkaset złotych w na przykład trzypokojowym mieszkaniu; wówczas mamy podaną wielkość mieszkania i cenę pokoju.
# tylko miasta z dużą ilością ofert
lista_miast <- count(oferty, miasto) %>% filter(n >= quantile(n, 0.75))
# odrzucamy skrajne 5% cen za metr (za dużo i za mało)
# i zostawiamy tylko miasta z 75% ofert
oferty <- filter(oferty,
miasto %in% lista_miast$miasto,
cena_za_metr >= quantile(oferty$cena_za_metr, 0.05),
cena_za_metr <= quantile(oferty$cena_za_metr, 0.95))
Po odrzuceniu zostaje nam 24445 ofert, w podziale na miasta wygląda to tak:
| miasto | n |
|---|---|
| Warszawa | 13173 |
| Kraków | 4656 |
| Katowice | 1460 |
| Poznań | 1172 |
| Wrocław | 1011 |
| Łódź | 912 |
| Gdańsk | 755 |
| Szczecin | 368 |
| Lublin | 312 |
| Gdynia | 247 |
| Gliwice | 199 |
| Toruń | 180 |
Dane mamy w pełni przygotowane. Teraz mięsko, czyli
Analiza
Na początek szybki przegląd rozkładów. Na kilku poniższych wykresach pionowa czerwona linia to średnia, a czarna - mediana. Na podstawie tych rozkładów widać, dlaczego wybieramy w późniejszych analizach medianę - średnie są większe od mediany dla wszystkich danych, co trochę może wprowadzać w błąd przy wnioskowaniu. Zobaczmy wielkości mieszkań:
ggplot(oferty) +
geom_density(aes(powierzchnia), fill = "lightgreen") +
geom_vline(xintercept = median(oferty$powierzchnia)) +
geom_vline(xintercept = mean(oferty$powierzchnia), color="red")
Połowa mieszkań wystawionych na wynajem ma powierzchnię mniejszą niż 57 m2 (oczywiście druga połowa ma większą). Ciekawe jak to ma się do rozkładu wielkości wszystkich mieszkań? Trzeba by sprawdzić w danych GUSu, pewnie ze spisów powszechnych. Proszę sprawdzić i napisać w komentarzu - w końcu chcę Was czegoś nauczyć, poszukiwanie informacji to jedna z najważniejszych umiejętności.
Znamy wielkość, a jak z ceną za całe mieszkanie?
ggplot(oferty) +
geom_density(aes(cena), fill = "lightgreen") +
geom_vline(xintercept = median(oferty$cena)) +
geom_vline(xintercept = mean(oferty$cena), color="red")
Mediana to 2600 złotych. Jeszcze tylko cena za metr kwadratowy - bo taka jednostka wydaje się najbardziej miarodajna przy porównywaniu ofert w poszczególnych miastach.
ggplot(oferty) +
geom_density(aes(cena_za_metr), fill = "lightgreen") +
geom_vline(xintercept = median(oferty$cena_za_metr)) +
geom_vline(xintercept = mean(oferty$cena_za_metr), color="red")
Na pierwszy rzut oka rozkład wygląda sensownie - po równo po obu stronach 46.56 zł/m2. Prawą stronę górki robi Warszawa - proszę sprawdzić ten sam rozkład dla ofert tylko z Warszawy (filtr na miasto).
Mamy jeszcze dane o ilości pokoi oraz o piętrze, na którym znajduje się mieszkanie. Te ostatnie jednak są dość kiepskiej jakości (w 13% to błędy, to wynik pobierania danych), ale z tego co mamy - 10 najbardziej popularnych to:
| Piętro | Procent ofert |
|---|---|
| 2 piętro z 4 | 6.44 |
| 1 piętro z 4 | 5.95 |
| 3 piętro z 4 | 4.99 |
| 1 piętro z 3 | 4.54 |
| 4 piętro z 4 | 3.73 |
| 2 piętro z 3 | 3.68 |
| 3 piętro z 3 | 3.57 |
| 3 piętro z 5 | 2.93 |
| 2 piętro z 5 | 2.81 |
| 1 piętro z 2 | 2.76 |
To jak z tymi pokojami?
| Liczba pokoi | Procent |
|---|---|
| 1 pokój | 8.7 |
| 2 pokoje | 48.7 |
| 3 pokoje | 30.9 |
| 4 pokoje | 9.0 |
| 5 pokoi | 2.2 |
| 6 pokoi | 0.4 |
oferty %>%
group_by(liczba_pokoi) %>%
summarise(n=n()) %>%
mutate(p=round(100*n/sum(n), 1)) %>%
ungroup() %>%
ggplot() +
geom_bar(aes(1, p, fill=liczba_pokoi), stat="identity") +
coord_polar(theta="y") +
labs(fill="Liczba pokoi") +
theme_void()
Najwięcej do wynajęcia jest mieszkań 2- (prawie połowa ofert!) i 3- pokojowych. Takich też zapewne najwięcej się buduje (i “po babci” zostało) - znowu do sprawdzenia w GUSie.
Zobaczmy jak to wygląda w poszczególnych miastach?
# rozkład procentowy po ilości pokoi
oferty %>%
group_by(miasto, liczba_pokoi) %>%
summarise(n=n()) %>%
mutate(p=100*n/sum(n)) %>%
ungroup() %>%
mutate(liczba_pokoi = factor(liczba_pokoi,
levels=rev(c("2 pokoje", "3 pokoje", "1 pokój",
"4 pokoje", "5 pokoi", "6 pokoi")))) %>%
ggplot() +
geom_bar(aes(miasto, p, fill=liczba_pokoi), stat="identity", color="black") +
coord_flip() +
labs(fill="Liczba pokoi", y="") +
theme(legend.position = "bottom") +
geom_hline(yintercept = c(25, 50, 75, 90, 95, 100)) +
scale_y_continuous(breaks = c(25, 50, 75, 90, 95, 100))
Zgodnie z oczekiwaniami - we wszystkich miastach 75% (lub więcej) to mieszkania dwu- i trzypokojowe. Ponadprzeciętne wartości to:
- w Warszawie czteropokojowe
- w Gliwicach, delikatnie mniej Szczecin i Poznań - jednopokojowe
Wiemy o liczbie pokoi w zależności od miasta, a czy z powierzchnią jest podobnie? Najpierw podzielimy powierzchnię na grupy: poniżej 38 m2, 38-60 m2, 60-90 m2 oraz ponad 90 m2:
oferty$powierzchnia_kat <- cut(oferty$powierzchnia,
breaks = c(0, 38, 60, 90, 1000))
I od razu zobaczmy jak to wygląda w poszczególnych miastach:
oferty %>%
group_by(miasto, powierzchnia_kat) %>%
summarise(n=n()) %>%
mutate(p=100*n/sum(n)) %>%
ungroup() %>%
mutate(powierzchnia_kat = factor(powierzchnia_kat,
levels=rev(levels(powierzchnia_kat)))) %>%
ggplot() +
geom_bar(aes(miasto, p, fill=powierzchnia_kat), stat="identity") +
coord_flip() +
labs(y="", fill="Powierzchnia:") +
scale_fill_manual(labels=c("ponad 90 m2", "60-90 m2", "38-60 m2", "poniżej 38 m2"),
values=c("#44ff44", "#44aa44", "#448844", "#444444")) +
geom_hline(yintercept = c(25, 50, 75, 90, 100)) +
scale_y_continuous(breaks = c(25, 50, 75, 90, 100))
Mamy potwierdzenie (nie wprost i wcale nie muszą to być zależne od siebie wartości - to statystyczna pułapka, w którą łatwo wpaść; przykład do znane wykresy pokazujące liczbę filmów z Cage’em versus liczba samobójstw - zbieżność nie musi oznaczać przyczynowości) poprzedniej obserwacji - w Warszawie jest więcej większych mieszkań (tych 4-pokojowych) - 25% to mieszkania ponad 90m2.
Teraz sprawdźmy zależności - czy większe mieszkanie jest droższe? Czy liczba pokoi ma jakieś znaczenie dla ceny? Czy liczba pokoi zależy od powierzchni mieszkania?
Na wszystkie te pytania można intuicyjnie odpowiedzieć tak, ale zobaczmy potwierdzenie w danych:
# cena zależna od ilości pokoi
ggplot(oferty) +
geom_boxplot(aes(liczba_pokoi, cena, group=liczba_pokoi),
color="black", fill="lightgreen") +
labs(title="Cena w zależności od liczby pokoi",
x="Liczba pokoi", y="Cena")

# wielkość w zależności od ilości pokoi
ggplot(oferty) +
geom_boxplot(aes(liczba_pokoi, powierzchnia, group=liczba_pokoi),
color="black", fill="lightgreen") +
labs(title="Powierzchnia w zależności od liczby pokoi",
x="Liczba pokoi", y="Powierzchnia mieszkania")
Jeszcze tylko rzucimy okiem na cenę mieszkania w zależności od ilości pomieszczeń, ale w rozbiciu na poszczególne miasta:
# j/w w rozbiciu na miasta
ggplot(oferty) +
geom_boxplot(aes(liczba_pokoi, cena/1000, group=liczba_pokoi),
color="black", fill="lightgreen") +
facet_wrap(~miasto, scales = "free_x", ncol = 3) +
labs(x="Liczba pokoi", y="Cena w tys.") +
coord_flip()
Tutaj widać interesujące rzeczy. Patrząc tylko na wykresy, bez zaglądania w dane i przede wszystkim ilość ofert w każdej z kategorii (przekrój miasto i liczba pokoi) widać:
- w Gdyni różnica w cenie pomiędzy 5 a 6 pokoi właściwie nie istnieje
- podobnie jest w Lublinie dla 4- i 5-pokojowych
- w Katowicach pięciopokojowe mogą okazać się tańsze niż czteropokojowe
- jeszcze bardziej widoczne jest to w Poznaniu dla 5- i 6-pokojowych
Bez dokładnej analizy danych, chociażby o standardzie i przede wszystkim lokalizacji w ramach miasta, powyższe wnioski mogą okazać się nieprawdziwe. Gdzieś tam na górze napisałem, że najbardziej sensowną i dającą najlepsze porównanie jest cena za metr kwadratowy. Sprawdźmy to, razem z całą drogą do potwierdzenia tej tezy.
# cena zależna od wielkości mieszkania
ggplot(oferty) +
geom_point(aes(powierzchnia, cena), alpha=0.1) +
geom_smooth(aes(powierzchnia, cena)) +
labs(x="Powierzchnia", y="Cena")
Widać prawie liniową zależność (współczynnik korelacji to 0.89), która jest intuicyjna: im większa chata, tym więcej trzeba płacić. To prowadzi do wniosku, że jednostkowa cena metra kwadratowego powinna być w miarę stała. Zobaczmy:
ggplot(oferty) +
geom_point(aes(powierzchnia, cena_za_metr), alpha=0.1) +
geom_smooth(aes(powierzchnia, cena_za_metr)) +
labs(x="Powierzchnia", y="Cena za m2")
Okazuje się jak widać, że niekoniecznie metr kwadratowy kosztuje zawsze tyle samo. To ma sens - najwięcej jest mieszkań o powierzchni w okolicy 45-55 m2 (rozkład z pierwszego wykresu), a więc i konkurencja w tym przedziale największa. Najprostszą metodą wygrania na rynku z konkurencją jest cena.
Spróbujmy przybliżyć fragment z minimum i coś z niego odczytać:
oferty %>%
ggplot() +
geom_point(aes(powierzchnia, cena_za_metr), alpha=0.1) +
geom_smooth(aes(powierzchnia, cena_za_metr)) +
coord_cartesian(xlim=c(40, 70), ylim=c(40, 50)) +
labs(x="Powierzchnia", y="Cena za m2")
Z wykresu odczytać można minimum dla 55 m2 przy cenie 45 zł/m2. A z obliczeń
# średnia powierzchnia - globalnie
sr_pow_global <- mean(oferty$powierzchnia)
# średnia cena za metr - globalnie
sr_cena_za_metr_global <- mean(oferty$cena_za_metr)
# mediany
med_pow_global <- median(oferty$powierzchnia)
med_cena_za_metr_global <- median(oferty$cena_za_metr)
wychodzi: średnie:
- powierzchnia: 67.28 m2
- cena za metr: 47.21 zł/m2
mediany:
- powierzchnia: 57 m2
- cena za metr: 46.56 zł/m2
Jak wygląda rozkład tego parametru dla wszystkich (no, tych 12 które zostały po czyszczeniu danych) miast?
| Liczba pokoi | średnia | mediana | minimum | maksimum |
|---|---|---|---|---|
| 1 pokój | 46.77 | 45.71 | 26.47 | 72.22 |
| 2 pokoje | 46.89 | 46.21 | 26.47 | 72.31 |
| 3 pokoje | 47.02 | 46.40 | 26.47 | 72.29 |
| 4 pokoje | 48.91 | 48.00 | 26.50 | 72.10 |
| 5 pokoi | 51.24 | 52.67 | 26.68 | 72.22 |
| 6 pokoi | 50.29 | 50.00 | 28.00 | 71.43 |
ggplot(oferty) +
geom_boxplot(aes(liczba_pokoi, cena_za_metr, group=liczba_pokoi),
color="black", fill="lightgreen") +
labs(x="Liczba pokoi", y="Cena za m2") +
scale_y_continuous(breaks = seq(20, 80, 5)) +
geom_hline(yintercept = sr_cena_za_metr_global, color="red") +
geom_hline(yintercept = med_cena_za_metr_global)
Jak widać zarówno wartości leżą wokół średniej (47.21 zł/m2 - linia czerwona na wykresie) jak i mediany (46.56 zł/m2) dla mieszkań do trzech pokoi. Trochę drożej “za jednostkę” robi się dla mieszkań większych, co było już widać na wykresie, który powiększaliśmy :)
Pierwszy poważny wniosek z tej całej analizy jest taki, że jeśli masz do wynajęcia (albo chcesz wynająć) najpopularniejze mieszkanie dwupokojowe około 50 m2 to powinno ono kosztować jakieś 47 zł/m2 czyli około 2350 zł. Czy więcej czy mniej - zależy od lokalizacji.
No to ile w Warszawie, ile w Poznaniu, a ile w Gliwicach? No ile?
Przygotujmy średnie (i mediany) dla ofert według miast i zobaczmy:
miasta <- oferty %>%
group_by(miasto) %>%
mutate(l_ofert = n()) %>%
mutate(sr_pow = mean(powierzchnia)) %>%
mutate(sr_cena = mean(cena)) %>%
mutate(sr_cena_za_metr = mean(cena_za_metr)) %>%
mutate(med_pow = median(powierzchnia)) %>%
mutate(med_cena = median(cena)) %>%
mutate(med_cena_za_metr = median(cena_za_metr)) %>%
ungroup() %>%
select(miasto, l_ofert,
sr_pow, sr_cena, sr_cena_za_metr,
med_pow, med_cena, med_cena_za_metr) %>%
unique()
| Miasto | Liczba ofert | Średnia pow. | Średnia cena | Średnia cena m2 | Mediana pow. | Mediana cena | Mediana cena m2 |
|---|---|---|---|---|---|---|---|
| Warszawa | 13173 | 77.00 | 4024.71 | 52.72 | 67.0 | 3400 | 52.73 |
| Gdańsk | 755 | 57.41 | 2619.10 | 45.97 | 51.0 | 2300 | 45.45 |
| Wrocław | 1011 | 58.18 | 2457.93 | 42.67 | 53.0 | 2200 | 41.67 |
| Kraków | 4656 | 56.96 | 2392.83 | 42.16 | 50.0 | 2000 | 40.32 |
| Gdynia | 247 | 64.93 | 2661.94 | 40.85 | 55.0 | 2200 | 37.00 |
| Katowice | 1460 | 53.52 | 2084.01 | 39.99 | 50.0 | 1950 | 39.27 |
| Poznań | 1172 | 51.69 | 1977.59 | 38.48 | 48.0 | 1700 | 36.76 |
| Lublin | 312 | 57.16 | 2129.42 | 38.07 | 54.0 | 1950 | 36.08 |
| Łódź | 912 | 57.48 | 2072.10 | 36.81 | 52.0 | 1850 | 35.00 |
| Szczecin | 368 | 54.22 | 1957.79 | 36.70 | 47.6 | 1850 | 34.76 |
| Gliwice | 199 | 49.21 | 1711.50 | 35.46 | 45.0 | 1500 | 33.77 |
| Toruń | 180 | 45.78 | 1485.99 | 32.75 | 41.3 | 1350 | 31.58 |
Jest pytanie - jest odpowiedź: Nasze 50 m2 w Warszawie powinno kosztować 2600 zł, w Poznaniu 1800 zł, a w Gliwicach 1700 zł. Zobaczmy tabelkę na wykresie. Na wykresie wszystko wygląda ładniej, chyba że wykres jest spierniczony. Wówczas można się do niego poprzypierniczać.
# mediana cena za metr wg miasta
miasta %>%
arrange(med_cena_za_metr) %>%
mutate(miasto=factor(miasto, levels=miasto)) %>%
ggplot() +
geom_bar(aes(miasto, med_cena_za_metr, fill=miasto),
stat="identity", show.legend = FALSE) +
geom_text(aes(miasto, med_cena_za_metr,
label=round(med_cena_za_metr, 1)),
hjust=1.2, vjust=0.2) +
geom_hline(yintercept = sr_cena_za_metr_global, color="red") +
geom_hline(yintercept = med_cena_za_metr_global) +
labs(x="", y="Cena za metr kwadratowy (mediana)") +
coord_flip()
Ameryki nie odkryliśmy - Warszawa jest najdroższa, potem są kolejne duże miasta. Sądziłem szczerze mówiąc, że Gdańsk będzie gdzieś w okolicach 4-5 miejsca, a nie drugi. Znaczy: można się czegoś dowiedzieć, zdziwić. Watro analizować. A że Toruń tańszy niż Łódź to totalne zaskoczenie.
Wiemy już o cenach, a gdzie są największe mieszkania do wynajęcia? Teoretycznie wszędzie powinno być w miarę podobnie, prawda?
# srednia powierzchnia wg miasta
miasta %>%
arrange(med_pow) %>%
mutate(miasto=factor(miasto, levels=miasto)) %>%
ggplot() +
geom_bar(aes(miasto, med_pow, fill=miasto),
stat="identity", show.legend = FALSE) +
geom_text(aes(miasto, med_pow, label=round(med_pow, 1)),
hjust=1.2, vjust=0.2) +
geom_hline(yintercept = sr_pow_global, color="red") +
geom_hline(yintercept = med_pow_global) +
labs(x="", y="Powierzchnia (mediana)") +
coord_flip()
I tu kolejne zaskoczenie - w Warszawie to mają wielkie mieszkania, po 70 metrów panie! Się powodzi w tej stolicy. Ale tak jest - mediana ma prawo być tak (stosunkowo) wysoka, bo sporo jest mieszkań powyżej 80 m2, kilkanaście nawet ponad 200 m2. Procentowo (w przedziałach co 25 m2) wygląda to tak:
Skoro wiemy jak różnią się miasta pomiędzy sobą, to czy w samych miastach są różnice i jak one są duże?
Trzeba pogrupować dane analogicznie jak wcześniej, tyle że schodzimy na poziom miast i dodatkowo dzielnic, zostawiając tylko cenę za metr kwadratowy oraz liczbę ofert z danej dzielnicy.
# średnie parametry wg dzielnic
dzielnice <- oferty %>%
group_by(miasto, dzielnica) %>%
mutate(l_ofert = n()) %>%
mutate(med_cena_za_metr = median(cena_za_metr)) %>%
ungroup() %>%
select(miasto, dzielnica, l_ofert, med_cena_za_metr) %>%
unique()
Ceny mieszkań w Warszawie
Jaki jest wynik? Najpierw Warszawa. Bo tutaj mieszkam i mogę skomentować wynik :)
dzielnice %>%
filter(miasto=="Warszawa") %>%
filter(l_ofert > quantile(l_ofert, 0.75)) %>%
arrange(med_cena_za_metr) %>%
mutate(dzielnica=factor(dzielnica, levels=dzielnica)) %>%
mutate(mediana = mean(med_cena_za_metr)) %>%
ggplot() +
geom_bar(aes(dzielnica, med_cena_za_metr, fill=dzielnica),
stat="identity", show.legend = FALSE) +
geom_text(aes(dzielnica, med_cena_za_metr,
label=round(med_cena_za_metr, 1)),
hjust=1.2, vjust=0.2, size=3) +
geom_text(aes(dzielnica, 1, label=l_ofert), hjust=0, vjust=0.2, size=3) +
geom_hline(aes(yintercept = mediana)) +
coord_flip() +
labs(x="Dzielnica", y="Cena za metr kwadratowy (mediana dla dzielnicy)") +
theme(legend.position = "none")
Dziwnie i podejrzanie wygląda ta Praga Północ na początku. Bierze się to z różnych sposobów zapisania nazwy dzielnicy (widać to też przy innych dzielnicach - Śródmieście czy Mokotów w kilku wariacjach). Jeśli ręcznie poprawimy dane (albo: wybierzemy tylko te rekordy, gdzie dzielnica w jakiś sposób przypomina ciąg “Praga Północ”) dostaniemy:
oferty %>%
filter(miasto=="Warszawa",
dzielnica %in% c("Praga-Północ", "Praga Północ", "Praga-Północ Praga")) %>%
select(cena_za_metr) %>%
summary()
## cena_za_metr
## Min. :28.12
## 1st Qu.:43.75
## Median :49.12
## Mean :51.54
## 3rd Qu.:61.90
## Max. :70.59
medianę ceny za metr kwadratowy równą nieco ponad 49 złotych, co jest o wiele bardziej prawdopobne niż prawie 61 zł/m2, które widać na wykresie. Poza północną Pragą dane mają sens - zawsze Śródmieście czy też Centrum jest najdroższe (w każdym właściwie mieście). Mokotów to dobra lokalizacja - wszędzie blisko, metro pod nosem, mi osobiście nie podobają się budynki. Wola analogicznie do Mokotowa, a do tego metro już jest albo za chwilę będzie. Z drugiej strony są blokowiska - Ursynów, Bemowo, Targówek czy Białołęka. Wesoła i Wawer to już prawie poza miastem, plusem Wesołej jest SKM.
Za ile powinno być wynajmowane konkretne mieszkanie?
Za przykład weźmy warszawską Białołękę i od razu zróbmy stosowną tabelkę (można wydrukować, wyciąć i schować do portfela):
| Liczba pokoi | Powierzchnia | Cena (średnia) | Cena (mediana) | Liczba ofert |
|---|---|---|---|---|
| 1 pokój | (35,40] | 1677 | 1590 | 3 |
| 2 pokoje | (30,35] | 2250 | 2250 | 2 |
| 2 pokoje | (35,40] | 1772 | 1700 | 9 |
| 2 pokoje | (40,45] | 1750 | 1800 | 6 |
| 2 pokoje | (45,50] | 2019 | 2100 | 13 |
| 2 pokoje | (50,55] | 2055 | 2150 | 10 |
| 2 pokoje | (55,60] | 1975 | 1925 | 6 |
| 2 pokoje | (65,70] | 1900 | 1900 | 1 |
| 3 pokoje | (50,55] | 2500 | 2500 | 1 |
| 3 pokoje | (55,60] | 2750 | 2750 | 2 |
| 3 pokoje | (60,65] | 2750 | 2650 | 4 |
| 3 pokoje | (65,70] | 2520 | 2500 | 15 |
Mieszkanie 45m2 na Białołęce powinno być wynajmowane za 1750 zł. Jeśli ktoś chce więcej - nie warto. Jeśli mniej - okazja! ;) Oczywiście zależy od standardu i lokalizacji. Jest 6 takich mieszkań, warto zobaczyć wszystkie. Patrząc na oferty - Tachomin i Aluzyjna w podobnej cenie, Odkryta nieco tańsze. I tego nie rozumiem (tej Aluzyjnej), ale to już mocno lokalna dygresja.
Ceny mieszkań w innych miastach
Ten sam kod wykonujemy dla pozostałych miast. I tutaj uwaga - też mamy błędnie wpisane nazwy dzielnic. Aby pozyć się tego typu wartości należałoby po wczytaniu danych porządnie je przeczyścić, niestety w dużym stopniu ręcznie (wyszukując i zamieniając odpowiednie ciągi znaków). Gratka mogłaby wprowadzić słowniki… nie jest to trudne i kosztowne.
Jeśli mieszkasz w którymś z miast - zapewne zobaczysz to, co ja widzę w Warszawie i Krakowie (znam topografię, wiem gdzie która dzielnica i co tam jest).
Następnym razem też zrobimy coś fajnego. Może nawet fajniejszego. Ale już tylko o Warszawie. I rowerach.
A na koniec nagranie, które jest tak stare jak internet. Do tego nagrania właśnie nawiązuje początek tego tekstu. Extreme Parental Advisory.