0.1 Wstęp

Rynek mieszkaniowy w Polsce podlega nieustannym turbulencjom związanymi z szeregiem czynników kształtujących równowagę rynkową. Ostatni okres kojarzony jest jednak z niepokojem względem kształtowania się ceny adekwatnej do warunków gospodarczych i otoczenia ekonomicznego deweloperów. Kolejne programy rządowe nie przynoszą oczekiwanych skutków, zaś ceny mieszkań naocznie rosną.

Kształtowanie się ceny zależy od szeregu czynników, zarówno ekonomicznych jak i innych, które można zaklasyfikować numerycznie lub opisowo. Nierzadko istotną rolę w doborze inwestycji w nieruchomości odgrywa położenie geograficzne. Mieszkanie w Warszawie czy Gdańsku wzbudza większe zainteresowanie niż odpowiednik w Rzeszowie czy Katowicach, choćby ze względu na średnie zarobki w obu otoczeniach miejskich. Tym samym interesujące wydają się wszelkie porównania oraz wizualne przedstawianie różnic kształtujących się pomiędzy cenami mieszkań.

Narodowy Bank Polski udostępnia cyklicznie kwartalne ceny mieszkań w formie przeciętnej ceny za metr kwadratowy w danym mieście wojewódzkim. Wybrane do raportu dane zostały podane w okresie od III kwartału 2006 do III kwartału 2021 włącznie i obejmują podział na rynek pierwotny i wtórny wraz z kolejnym wewnętrznym rozdzieleniem na ceny ofertowe i transakcyjne dla każdego rodzaju. Ceny zostały podane w walucie PLN.

Przygotowanie danych poza zakresem R objęło podział pierwotnego pliku w formacie .xls na cztery osobne arkusze w formacie .csv z danymi odpowiadającymi kolejno:

  • rynek pierwotny: ceny ofertowe;

  • rynek pierwotny: ceny transakcyjne;

  • rynek wtórny: ceny ofertowe;

  • rynek wtórny: ceny transakcyjne.

Rynek nieruchomości jest na tyle złożony, że trudno postawić jedno pytanie badawcze, które mogłoby skupić zarówno analizę behawioralną kupujących oraz uwzględnienie innych czynników ekonomicznych, politycznych i społecznych. Tym samym celem raportu jest jak najszersze oszacowanie zmian w obrębie zmian cen i podstawowych operacji statystycznych wykonanu w programie R z wykorzystaniem środowiska programistycznego jakim jest RStudio.

Analiza będzie bazować na podstawowych statystykach oszacowanych na podstawie dostępnych danych. Autorzy pragną zaprezentować oraz krótko oszacować:

  • Rozkład średnich cen ofertowych mieszkań na rynku wtórnym,

  • Kształtowanie cen ofertowych na rynku pierwotnym,

  • Relację odchyleń standardowych ofertowych cen mieszkań na rynku wtórnym w dwóch najbardziej zamożnych miastach,

  • Kształtowanie przeciętnej ceny transakcyjnej na rynku pierwotnym,

  • Kształtowanie przeciętnej ceny transakcyjnej w Gdańsku wraz z trendem,

  • Porównanie ceny ofertowej na rynku pierwtonym sześciu najdroższych miast z wyłączeniem Warszawy względem średniej,

  • Porównanie cen mieszkań w Warszawie na podstawie wszystkich rynków.

Na podstawie oszacowanych danych zostanie zaprezentowany krótki wniosek względem kondycji rynku nieruchomości w Polsce.

0.2 Importowanie danych oraz odczytanie wstępnych informacji

Dane zostały wczytane i oznaczone roboczymi etykietami, kolejno rpo, rpt, rwo, rwt.

setwd("/Users/michalniemczal/Desktop/AG2/AD/Gmail")
rpo <- read.csv("rpierwotny_cofertowe.csv", sep=";", dec=",", stringsAsFactors = T)
rpt <- read.csv("rpierwotny_ctrans.csv", sep=";", dec=",", stringsAsFactors = T)
rwo <- read.csv("rwtorny_cofertowe.csv", sep=";", dec=",", stringsAsFactors = T)
rwt <- read.csv("rwtorny_ctrans.csv", sep=";", dec=",", stringsAsFactors = T)

W celu sprawdzenia informacji na temat zaimportowanych danych wykonano podstawowe podsumowania na przykładzie rpo:

head(rpo)
tail(rpo)
str(rpo)
## 'data.frame':    61 obs. of  18 variables:
##  $ Kwartał     : Factor w/ 61 levels "I 2007","I 2008",..: 31 47 1 16 32 48 2 17 33 49 ...
##  $ Białystok   : int  2727 2727 4181 4725 4199 4995 5128 5651 5115 4725 ...
##  $ Bydgoszcz   : int  3243 3947 4501 5700 4994 4829 4893 5035 4959 4989 ...
##  $ Gdańsk      : int  5004 6199 6437 7999 8053 7402 7210 8509 8454 6609 ...
##  $ Gdynia      : int  4937 5284 6466 8934 8114 7887 7737 7897 7169 6342 ...
##  $ Katowice    : int  3986 4062 4518 5181 6236 6458 6258 6599 6303 6677 ...
##  $ Kielce      : int  2919 3493 3382 3902 4651 4475 4529 5281 5396 5208 ...
##  $ Kraków      : int  6021 7929 8247 8129 8420 8355 8084 8034 8012 7751 ...
##  $ Lublin      : int  3456 3314 3604 4143 4645 5047 5011 5174 5170 5266 ...
##  $ Łódź        : int  3210 4237 4927 5453 5201 5062 5048 4962 5480 5329 ...
##  $ Olsztyn     : int  4000 4800 5149 4776 4900 4900 4800 4800 4924 4761 ...
##  $ Opole       : int  3343 NA NA NA 4784 4937 4920 4931 4943 4968 ...
##  $ Poznań      : int  4770 4827 7275 7360 6838 7564 7480 7338 7320 7277 ...
##  $ Rzeszów     : int  2862 3401 3420 4080 4069 4357 4188 4215 4433 4069 ...
##  $ Szczecin    : int  3215 3679 4749 5050 5035 5731 5723 5664 5521 5469 ...
##  $ Warszawa    : int  5873 6095 7509 8000 8740 9561 9427 9300 9235 9821 ...
##  $ Wrocław     : int  4750 5759 6309 6294 6444 5495 5728 6299 5704 5027 ...
##  $ Zielona.Góra: int  2754 2869 2872 4153 4208 3965 3965 3986 4012 3892 ...
summary(rpo)
##     Kwartał     Białystok      Bydgoszcz        Gdańsk          Gdynia     
##  I 2007 : 1   Min.   :2727   Min.   :3243   Min.   : 5004   Min.   : 4937  
##  I 2008 : 1   1st Qu.:4791   1st Qu.:4920   1st Qu.: 6248   1st Qu.: 6294  
##  I 2009 : 1   Median :4886   Median :5100   Median : 6568   Median : 6785  
##  I 2010 : 1   Mean   :5081   Mean   :5426   Mean   : 7200   Mean   : 7267  
##  I 2011 : 1   3rd Qu.:5236   3rd Qu.:6041   3rd Qu.: 8267   3rd Qu.: 7912  
##  I 2012 : 1   Max.   :7621   Max.   :7567   Max.   :10310   Max.   :11193  
##  (Other):55                                                                
##     Katowice        Kielce         Kraków          Lublin          Łódź     
##  Min.   :3986   Min.   :2919   Min.   : 6021   Min.   :3314   Min.   :3210  
##  1st Qu.:5413   1st Qu.:4783   1st Qu.: 6670   1st Qu.:5014   1st Qu.:4906  
##  Median :5817   Median :4907   Median : 7209   Median :5126   Median :5147  
##  Mean   :5994   Mean   :4980   Mean   : 7472   Mean   :5286   Mean   :5325  
##  3rd Qu.:6458   3rd Qu.:5112   3rd Qu.: 8012   3rd Qu.:5287   3rd Qu.:5475  
##  Max.   :8387   Max.   :6633   Max.   :10605   Max.   :7965   Max.   :8006  
##                                                                             
##     Olsztyn         Opole          Poznań        Rzeszów        Szczecin   
##  Min.   :4000   Min.   :3343   Min.   :4770   Min.   :2862   Min.   :3215  
##  1st Qu.:4800   1st Qu.:4764   1st Qu.:6425   1st Qu.:4254   1st Qu.:4890  
##  Median :4924   Median :4840   Median :6600   Median :4952   Median :5031  
##  Mean   :5241   Mean   :5035   Mean   :6802   Mean   :4834   Mean   :5488  
##  3rd Qu.:5600   3rd Qu.:5273   3rd Qu.:7277   3rd Qu.:5148   3rd Qu.:5731  
##  Max.   :6921   Max.   :6441   Max.   :8656   Max.   :7271   Max.   :8775  
##                 NA's   :3                                                  
##     Warszawa        Wrocław      Zielona.Góra 
##  Min.   : 5873   Min.   :4750   Min.   :2754  
##  1st Qu.: 7839   1st Qu.:6020   1st Qu.:3660  
##  Median : 8146   Median :6281   Median :3870  
##  Mean   : 8675   Mean   :6550   Mean   :4035  
##  3rd Qu.: 9561   3rd Qu.:6526   3rd Qu.:4012  
##  Max.   :11406   Max.   :9965   Max.   :6820  
## 

Zauważono, że wartości numeryczne zostały zaimportowane w formie int (integer). Z racji późniejszych kalkulacji oraz form wizualizacji danych nastąpiło przekształcenie danych w formie int spośród wszystkich ramek na wartości numeryczne.

rpo$Białystok <- as.numeric(rpo$Białystok)
rpo$Bydgoszcz <- as.numeric(rpo$Bydgoszcz)
rpo$Gdańsk <- as.numeric(rpo$Gdańsk)
rpo$Gdynia <- as.numeric(rpo$Gdynia)
rpo$Katowice <- as.numeric(rpo$Katowice)
rpo$Kielce <- as.numeric(rpo$Kielce)
rpo$Kraków <- as.numeric(rpo$Kraków)
rpo$Lublin <- as.numeric(rpo$Lublin)
rpo$Łódź <- as.numeric(rpo$Łódź)
rpo$Olsztyn <- as.numeric(rpo$Olsztyn)
rpo$Opole <- as.numeric(rpo$Opole)
rpo$Poznań <- as.numeric(rpo$Poznań)
rpo$Rzeszów <- as.numeric(rpo$Rzeszów)
rpo$Szczecin <- as.numeric(rpo$Szczecin)
rpo$Warszawa <- as.numeric(rpo$Warszawa)
rpo$Wrocław <- as.numeric(rpo$Wrocław)
rpo$Zielona.Góra <- as.numeric(rpo$Zielona.Góra)

rpt$Białystok <- as.numeric(rpt$Białystok)
rpt$Bydgoszcz <- as.numeric(rpt$Bydgoszcz)
rpt$Gdańsk <- as.numeric(rpt$Gdańsk)
rpt$Gdynia <- as.numeric(rpt$Gdynia)
rpt$Katowice <- as.numeric(rpt$Katowice)
rpt$Kielce <- as.numeric(rpt$Kielce)
rpt$Kraków <- as.numeric(rpt$Kraków)
rpt$Lublin <- as.numeric(rpt$Lublin)
rpt$Łódź <- as.numeric(rpt$Łódź)
rpt$Olsztyn <- as.numeric(rpt$Olsztyn)
rpt$Opole <- as.numeric(rpt$Opole)
rpt$Poznań <- as.numeric(rpt$Poznań)
rpt$Rzeszów <- as.numeric(rpt$Rzeszów)
rpt$Szczecin <- as.numeric(rpt$Szczecin)
rpt$Warszawa <- as.numeric(rpt$Warszawa)
rpt$Wrocław <- as.numeric(rpt$Wrocław)
rpt$Zielona.Góra <- as.numeric(rpt$Zielona.Góra)

rwo$Białystok <- as.numeric(rwo$Białystok)
rwo$Bydgoszcz <- as.numeric(rwo$Bydgoszcz)
rwo$Gdańsk <- as.numeric(rwo$Gdańsk)
rwo$Gdynia <- as.numeric(rwo$Gdynia)
rwo$Katowice <- as.numeric(rwo$Katowice)
rwo$Kielce <- as.numeric(rwo$Kielce)
rwo$Kraków <- as.numeric(rwo$Kraków)
rwo$Lublin <- as.numeric(rwo$Lublin)
rwo$Łódź <- as.numeric(rwo$Łódź)
rwo$Olsztyn <- as.numeric(rwo$Olsztyn)
rwo$Opole <- as.numeric(rwo$Opole)
rwo$Poznań <- as.numeric(rwo$Poznań)
rwo$Rzeszów <- as.numeric(rwo$Rzeszów)
rwo$Szczecin <- as.numeric(rwo$Szczecin)
rwo$Warszawa <- as.numeric(rwo$Warszawa)
rwo$Wrocław <- as.numeric(rwo$Wrocław)
rwo$Zielona.Góra <- as.numeric(rwo$Zielona.Góra)

rwt$Białystok <- as.numeric(rwt$Białystok)
rwt$Bydgoszcz <- as.numeric(rwt$Bydgoszcz)
rwt$Gdańsk <- as.numeric(rwt$Gdańsk)
rwt$Gdynia <- as.numeric(rwt$Gdynia)
rwt$Katowice <- as.numeric(rwt$Katowice)
rwt$Kielce <- as.numeric(rwt$Kielce)
rwt$Kraków <- as.numeric(rwt$Kraków)
rwt$Lublin <- as.numeric(rwt$Lublin)
rwt$Łódź <- as.numeric(rwt$Łódź)
rwt$Olsztyn <- as.numeric(rwt$Olsztyn)
rwt$Opole <- as.numeric(rwt$Opole)
rwt$Poznań <- as.numeric(rwt$Poznań)
rwt$Rzeszów <- as.numeric(rwt$Rzeszów)
rwt$Szczecin <- as.numeric(rwt$Szczecin)
rwt$Warszawa <- as.numeric(rwt$Warszawa)
rwt$Wrocław <- as.numeric(rwt$Wrocław)
rwt$Zielona.Góra <- as.numeric(rwt$Zielona.Góra)

W celu zobrazowania potencjalnego rozkładu cen na poszczególnych rynkach autorzy zdecydowali się na wizualizację rynku rpo za pomocą narzędzia matplot jako poglądowe ujęcie danych. Jako że matplot najlepiej operuje na macierzach, a nie ramkach danych, utworzono kopię rpo w ujęciu macierzowym.

rpo_matrix <- as.matrix(rpo)
head(rpo_matrix)
##      Kwartał    Białystok Bydgoszcz Gdańsk  Gdynia  Katowice Kielce Kraków 
## [1,] "III 2006" "2727"    "3243"    " 5004" " 4937" "3986"   "2919" " 6021"
## [2,] "IV 2006"  "2727"    "3947"    " 6199" " 5284" "4062"   "3493" " 7929"
## [3,] "I 2007"   "4181"    "4501"    " 6437" " 6466" "4518"   "3382" " 8247"
## [4,] "II 2007"  "4725"    "5700"    " 7999" " 8934" "5181"   "3902" " 8129"
## [5,] "III 2007" "4199"    "4994"    " 8053" " 8114" "6236"   "4651" " 8420"
## [6,] "IV 2007"  "4995"    "4829"    " 7402" " 7887" "6458"   "4475" " 8355"
##      Lublin Łódź   Olsztyn Opole  Poznań Rzeszów Szczecin Warszawa Wrocław
## [1,] "3456" "3210" "4000"  "3343" "4770" "2862"  "3215"   " 5873"  "4750" 
## [2,] "3314" "4237" "4800"  NA     "4827" "3401"  "3679"   " 6095"  "5759" 
## [3,] "3604" "4927" "5149"  NA     "7275" "3420"  "4749"   " 7509"  "6309" 
## [4,] "4143" "5453" "4776"  NA     "7360" "4080"  "5050"   " 8000"  "6294" 
## [5,] "4645" "5201" "4900"  "4784" "6838" "4069"  "5035"   " 8740"  "6444" 
## [6,] "5047" "5062" "4900"  "4937" "7564" "4357"  "5731"   " 9561"  "5495" 
##      Zielona.Góra
## [1,] "2754"      
## [2,] "2869"      
## [3,] "2872"      
## [4,] "4153"      
## [5,] "4208"      
## [6,] "3965"

Dodano wektor Miast (Cities), który przyczynił się do powstania legendy, aby zaprezentowane dane były bardziej czytelne oraz rozróżnialne.

Cities <- c("Białystok", "Bydgoszcz", "Gdańsk", "Gdynia", "Katowice", "Kielce",
            "Kraków", "Lublin", "Łódź","Olsztyn", "Opole", "Poznań", "Rzeszów",
            "Szczecin", "Warszawa", "Wrocław", "Zielona Góra")

Tym samym skonstruowano poniższy wykres.

matplot(rpo_matrix, type="l", lty = c(1:17), lwd = 2, col=c(1:17),
        xlab = "Czas w Kwartałach",
        ylab = "Cena w złotówkach za metr kwadratowy",
        main = "Ceny mieszkań na rynku pierwotnym w miastach wojewódzkich w Polsce")
## Warning in xy.coords(x, y, xlabel, ylabel, log = log, recycle = TRUE): pojawiły
## się wartości NA na skutek przekształcenia
## Warning in xy.coords(x, y, xlabel, ylabel, log): pojawiły się wartości NA na
## skutek przekształcenia
par(mar=c(5, 5, 5, 8.1), xpd=TRUE)
legend("topright", inset=c(-0.3,0), legend=Cities, lty = c(1:17), lwd = 2, col=c(1:17),
       horiz=F, xpd = T, title = "Miasta")

Jak można zauważyć, wykres jest niedoskonały. Niesie ze sobą ograniczenia zarówno narzędzia, jakim jest matplot oraz dokumentowania w formie R-Markdown. Poniżej zaprezentowano w formie wyeksportowanego zdjęcia wykres z uwzględnieniem legendy:

Widać, że zbiorowe prezentowanie rynków niesie ze sobą przesyt informacyjny i nawet obecność legendy nie jest wystarczającą suplementacją odczytywania danych. Tym samym narzędzie matplot należy traktować jedynie jako opcjonalną wizualizację wstępnych obserwacji, zaś właściwe wykresy zostaną przedstawione za pomocą pakietu ggplot2.

Od tej pory pierwotne faktory “Kwartał” nie będą potrzebne, gdyż zostaną później zastąpione odpowiednim formatowaniem. Tym samym usunięto kolumny zawierające niepotrzebne faktory.

rpo$Kwartał <- NULL
rpt$Kwartał <- NULL
rwo$Kwartał <- NULL
rwt$Kwartał <- NULL

0.3 Lokalizacja brakujących danych oraz zastępowanie ich medianą

Surowe dane nierzadko wymagają dodatkowej uwagi ze względu na potencjalne błędy, nienaturalne odchylenia czy brakujące elementy. W celu uzyskania najbardziej przybliżonego do rzeczywistości obrazu na badane elementy, należy upewnić się czy dane są kompletne.

rpo[!complete.cases(rpo),]
rpt[!complete.cases(rpt),]
rwo[!complete.cases(rwo),]
rwt[!complete.cases(rwt),]

Wynikiem sprawdzenia, okazało się, że ramki danych rpo oraz rpt zawierają puste rekordy. Manualne sprawdzenie danych wykazało:

  • brak trzech rekordów w okresach 4 kwartał 2006, 1 kwartał 2007 i 2 kwartał 2007 w Opolu dla rynku pierwotnego, cen ofertowych,

  • brak jednego rekordu w 1 kwartale 2007 w Opolu dla rynku pierwotnego, cen transakcyjnych.

Pozostałe dane są kompletne. Bazując na pierwotnych podsumowaniach należy także stwierdzić, że nie nastąpiło żadne szczególne odchylenie. Autorzy nie mają także możliwości weryfikacji potencjalnych błędów.

Przystąpiono do usuwania wartości nieznanych. Poniżej przedstawiono alternatywne sposoby na wskazywanie brakujących danych w kolumnie odpowiadającej Opolu dla rpo:

is.na(rpo$Opole)
##  [1] FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [37] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [49] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [61] FALSE
rpo[is.na(rpo$Opole),]

Przy brakujących danych istnieje kilka sposobów na zastąpienie pustych rekordów zamiast usuwania całych wierszy. Poniżej zaprezentowano wybrane metody oraz uzasadnienie wyboru:

  • Uzupełnienie o wiedzę faktyczną - jak wspomniano, weryfikacja dostępnych danych jest niemożliwa w wykonaniu autorów.

  • Wykorzystanie danych z innego źródła - zaburzyłoby to podstawową analizę danych oraz byłoby zbyt czasochłonne względem oczekiwanych korzyści.

  • Zastąpienie brakujących rekordów medianą lub średnią - metoda adekwatna do potrzeb projektowych.

Brakujące wartości można zastąpić na kilka sposobów; puste dane można obliczyć albo za pomocą średniej lub mediany z brakującego okresu tudzież jako średnia lub mediana dla brakującego miasta.

Wykres w poprzednim rozdziale pokazał jasno, że wartości badane (w tym przypadku ceny) w badanym okresie zdecydowanie wzrosły. Tym samym druga metoda może prowadzić do wypaczeń zarówno w przypadku średniej jak i mediany. Innym wnioskiem jaki można było wyciągnąc z wykresu to różnice pomiędzy średnimi cenami w poszczególnych miastach co przejawiało się w odległości pomiędzy liniami reprezentującymi poszczególne miasta.

Wybrano zatem pierwszy sposób z uwzględnieniem mediany. Zdefiniowano wartości statystyki dla każdego brakującego kwartału.

rpoy2006q4 <- median(as.numeric(rpo[2,]), na.rm = T,)
rpoy2007q1 <- median(as.numeric(rpo[3,]), na.rm = T)
rpoy2007q2 <- median(as.numeric(rpo[4,]), na.rm = T)
rpty2007q1 <- median(as.numeric(rpt[3,]), na.rm = T)

Za pomocą filtrowania oraz subsettingu uzupełniono obliczone wartości w puste miejsca odpowiednich ramek danych. Aby zaadresować unikalny wiersz wykorzystano wartość w pierwszej kolumnie odpowiadającej Białemustokowi.

rpo[is.na(rpo$Opole) & rpo$Białystok == 2727, "Opole"] <- rpoy2006q4
rpo[is.na(rpo$Opole) & rpo$Białystok == 4181, "Opole"] <- rpoy2007q1
rpo[is.na(rpo$Opole) & rpo$Białystok == 4725, "Opole"] <- rpoy2007q2
rpt[is.na(rpt$Opole) & rpt$Białystok == 3500, "Opole"] <- rpty2007q1

Z racji faktu, iż puste rekordy przejawiały się w pierwszych wierszach poszczególnych data frames, do sprawdzenia wystarczy funkcja head() dla obu rynków. Niemniej w celu absolutnej pewności zastosowano powtórnie linijki, których zadaniem było wskazanie brakujących rekordów.

head(rpo)
head(rpt)
rpo[!complete.cases(rpo),]
rpt[!complete.cases(rpt),]

Uzupełnianie brakujących danych zostało ukończone z powodzeniem. Tym samym można przystąpić do analizy i wizualizacji wyników.

0.4 Dodanie podstawowych statystyk oraz wektorów do ramek danych

Pierwszym krokiem w celu dodania wartości obliczeniowej dla badanych rynków będzie dodanie podstawowych statystyk takich jak średnia, mediana, odchylenie standardowe, minimalna wartość oraz maksymalna wartość. Najprostszym sposobem w tym przypadku było rozpisanie funkcji, która zebrałaby odpowiednie dane w postaci wektorów oraz połączenie otrzymanych ramek danych z danymi rynkowymi.

basic_stats <- function(x, digits = 3L, ...) {
  x <- c(x, recursive = TRUE, use.names = FALSE)
  res <- c(mean = mean(x, ...), sd = sd(x, ...),
           median = median(x, ...), max = max(x, ...), min = min(x, ...))
  round(res, digits = 0)
}

rpo <- cbind(rpo, t(apply(rpo, 1, basic_stats, na.rm = TRUE)))
rpt <- cbind(rpt, t(apply(rpt, 1, basic_stats, na.rm = TRUE)))
rwo <- cbind(rwo, t(apply(rwo, 1, basic_stats, na.rm = TRUE)))
rwt <- cbind(rwt, t(apply(rwt, 1, basic_stats, na.rm = TRUE)))

Po usunięciu kolumny “Kwartał” , badane rynki nie posiadają zmiennej czasowej. Za pomocą pakietu zoo, zwektoryzowano zmienną date dla każdego rynku oraz dołączono kolumnę do każdej z badanych ramek.

date <- c("Q3 2006", "Q4 2006", "Q1 2007", "Q2 2007","Q3 2007",
          "Q4 2007", "Q1 2008", "Q2 2008", "Q3 2008","Q4 2008",
          "Q1 2009", "Q2 2009", "Q3 2009", "Q4 2009", "Q1 2010",
          "Q2 2010", "Q3 2010", "Q4 2010", "Q1 2011", "Q2 2011",
          "Q3 2011", "Q4 2011", "Q1 2012", "Q2 2012", "Q3 2012",
          "Q4 2012", "Q1 2013", "Q2 2013", "Q3 2013", "Q4 2013",
          "Q1 2014", "Q2 2014", "Q3 2014", "Q4 2014", "Q1 2015",
          "Q2 2015", "Q3 2015", "Q4 2015", "Q1 2016", "Q2 2016",
          "Q3 2016", "Q4 2016", "Q1 2017", "Q2 2017", "Q3 2017",
          "Q4 2017", "Q1 2018", "Q2 2018", "Q3 2018", "Q4 2018",
          "Q1 2019", "Q2 2019", "Q3 2019", "Q4 2019", "Q1 2020",
          "Q2 2020", "Q3 2020", "Q4 2020", "Q1 2021", "Q2 2021",
          "Q3 2021")
library(zoo)
## 
## Dołączanie pakietu: 'zoo'
## Następujące obiekty zostały zakryte z 'package:base':
## 
##     as.Date, as.Date.numeric
as.yearqtr(format(date), "Q%q %Y")
##  [1] "2006 Q3" "2006 Q4" "2007 Q1" "2007 Q2" "2007 Q3" "2007 Q4" "2008 Q1"
##  [8] "2008 Q2" "2008 Q3" "2008 Q4" "2009 Q1" "2009 Q2" "2009 Q3" "2009 Q4"
## [15] "2010 Q1" "2010 Q2" "2010 Q3" "2010 Q4" "2011 Q1" "2011 Q2" "2011 Q3"
## [22] "2011 Q4" "2012 Q1" "2012 Q2" "2012 Q3" "2012 Q4" "2013 Q1" "2013 Q2"
## [29] "2013 Q3" "2013 Q4" "2014 Q1" "2014 Q2" "2014 Q3" "2014 Q4" "2015 Q1"
## [36] "2015 Q2" "2015 Q3" "2015 Q4" "2016 Q1" "2016 Q2" "2016 Q3" "2016 Q4"
## [43] "2017 Q1" "2017 Q2" "2017 Q3" "2017 Q4" "2018 Q1" "2018 Q2" "2018 Q3"
## [50] "2018 Q4" "2019 Q1" "2019 Q2" "2019 Q3" "2019 Q4" "2020 Q1" "2020 Q2"
## [57] "2020 Q3" "2020 Q4" "2021 Q1" "2021 Q2" "2021 Q3"
date <- as.Date(as.yearqtr(format(date), "Q%q %Y"))
rpo <- cbind(date, rpo)
rpt <- cbind(date, rpt)
rwo<- cbind(date, rwo)
rwt <- cbind(date, rwt)

Dodano także utworzony manualnie wektor łączący poszczególne podokresy w ujęcie roczne. Wektor “ROK” został także dodany do poszczególnych ramek.

ROK <- c(2006,
         2006,
         2007,
         2007,
         2007,
         2007,
         2008,
         2008,
         2008,
         2008,
         2009,
         2009,
         2009,
         2009,
         2010,
         2010,
         2010,
         2010,
         2011,
         2011,
         2011,
         2011,
         2012,
         2012,
         2012,
         2012,
         2013,
         2013,
         2013,
         2013,
         2014,
         2014,
         2014,
         2014,
         2015,
         2015,
         2015,
         2015,
         2016,
         2016,
         2016,
         2016,
         2017,
         2017,
         2017,
         2017,
         2018,
         2018,
         2018,
         2018,
         2019,
         2019,
         2019,
         2019,
         2020,
         2020,
         2020,
         2020,
         2021,
         2021,
         2021)
ROK <- as.factor(ROK)
rpo <-cbind(ROK, rpo)
rpt <- cbind(ROK, rpt)
rwo<- cbind(ROK, rwo)
rwt <- cbind(ROK, rwt)

Tym samym dane są w pełni gotowe do analizy.

head(rpo)
head(rpt)
head(rwo)
head(rwt)

Zebrano ostateczne ramki danych, które zostaną wykorzystane do analizy. W celu zapobieżenia błędom, utworzono kopie zapasowe w postaci kopii ramek danych.

rpo_backup <- rpo
rpt_backup <- rpt
rwo_backup <- rwo
rwt_backup <- rwt

0.5 Analiza danych

0.5.1 Rozkład średniej ceny ofertowej na rynku wtórnym

Z racji szerokich możliwości przygotowanych danych, autorzy zdecydowali się na zaledwie kilka analiz ukazujących możliwości prezentacyjne oraz wizualizacyjne względem badanych rynków. Analizy są dobrane subiektywnie mają za zadanie pokazać badany zbiór cen z kilku perspektyw. Wykresy zostały wykonane z pomocą pakietów “ggplot2” oraz “gridExtra”.

Pierwszym elementem badanym jest rozkład przeciętnej ceny każdego kwartału za pomocą histogramu na rynku wtórnym, wśród cen ofertowych.

library(ggplot2)
sum_av <- ggplot(data=rwo, aes(x=mean)) +
  geom_histogram(bindwidth =10, fill="White", colour="Blue") +
  xlab("Wartość uśrednionej ceny mieszkań na rwo") +
  ylab("") +
  ggtitle("Rozkład średniej ceny za m2") +
  theme(plot.title = element_text(hjust = 0.5))
## Warning: Ignoring unknown parameters: bindwidth
sum_av
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Jak można zauważyć z wykresu, rozkład uśrednionych cen za metr kwadratowy na rynku wtórnym (spośród cen ofertowych) przybierał włąściwości rozkładu normalnego skupiając się wokół centrum w okolicach 5500 złotych za metr kwadratowy. Uzasadnienie faktyczne takiego stanu odnajduje się w rzeczywistości. Spośród najbardziej zamożnych miast, kilka wyróżnia się wysoką ceną za metr kwadratowy, jak na przykład Gdańsk czy Poznań. Istnieją jednak także miasta, które nie są dla większości pierwszym wyborem zamieszkania, relatywizując do zamożniejszych odpowiedników. Wówczas (w tym przypadku właściciele mieszkań) obniżają ceny oferowane aby zwiększyć popyt na sprzedawane dobro.

0.5.2 Kształtowanie ceny ofertowej na rynku pierwotnym

Rozkład nie jest jedynym elementem, dzięki któremu można odczytać wartości danych. Kolejnym krokiem w analizie jest uporządkowanie maksymalnych cen ofertowych mieszkań na rynku pierwotnym od najmniejszej do największej z uwzględnieniem kwartału, w jakim wystąpiła dana cena. W tym celu autorzy posłużyli się pakietem “dplyr”.

library(dplyr)
## 
## Dołączanie pakietu: 'dplyr'
## Następujące obiekty zostały zakryte z 'package:stats':
## 
##     filter, lag
## Następujące obiekty zostały zakryte z 'package:base':
## 
##     intersect, setdiff, setequal, union
ex_1 <- rpo %>% select(max, date) %>% arrange((max))
ex_1

Dane zaprezentowano także za pomocą wykresu:

vis_ex_1 <- ggplot(data=ex_1, aes(x=date, y=max)) + 
    geom_line() +
    geom_point(aes(size=max)) + 
  xlab("Czas") +
  ylab("Maks. cena ofertowa na r. pierwotnym") +
  ggtitle("Kształtowanie cen ofertowych na rynku pierwotnym") +
  theme(plot.title = element_text(hjust = 0.5))
vis_ex_1

Wizualizacja pokrywa się z otrzymanymi danymi zmiennej ex_1. Od 2009 roku, rynek nie zaobserwował tak wysokich cen za metr kwadratowy jak w ostatnich podokresach. Tym samym widać zarówno okres spekulacji pomiędzy 2008-10 oraz załamanie cen na rynku pierwotnym, którego efektem był kryzys mieszkaniowy w 2012 roku, a także niebezpieczną tendencję wzrostu cen, która trwa aż do ostatniego badanego kwartału. Zauważa się tym samym niebezpieczeństwo powstania bańki na rynku nieruchomości oraz związanych z nią potencjalnych kryzysów. Innym wytłumaczeniem powstałego trendu, według niektórych analityków, jest moda mieszkaniowa oraz boom na rynku deweloperskim.

0.5.3 Zestawienie odchyleń dwóch najdroższych miast

Według portalu samorządowego, najdroższe mieszkania w Polsce, zarówno na rynku pierwotnym jak i wtórnym, konsument może nabyć w Warszawie oraz Gdańsku. Potwierdzają to także dane zebrane na potrzeby raportu. Interesującym aspektem wydaje się jednak kształtowanie różnic pomiędzy cenami, gdyż w świadomości publicznej, stolica Polski była zdecydowanie kojarzona z najwyższymi cenami.

W tym celu przygotowano pogrupowane względem odchylenia standardowego zestawienie porównawcze w formie listy o malejącej cenie ofertowej z uwzględnieniem daty danej obserwacji na rynku wtórnym:

ex_2 <- rwo %>% select(Warszawa, Gdańsk, sd, date) %>% group_by(sd) %>% arrange(desc(date))
ex_2

Należy dostrzec pewne odniesienia względem wcześniejszych badań. Najwyższą cenę za metr kwadratowy czytelnik zaobserwuje w pierwszych rzędach, które kształtują się odwrotną chronologią. Oznacza to, że wspomniana wcześniej bańka mieszkaniowa wciąż się napełnia, a tendencja wzrostowa, na bazie różnic pomiędzy kolejnymi obserwacjami w ujęciu łańcuchowym wciąż się rozpędza.

Do zaobserwowania różnic pomiędzy odchyleniami, autorzy wykorzystali kolejny wykres:

vis_ex_2 <- ggplot(data=ex_2, aes(x=Warszawa, y=Gdańsk, color=sd)) +
         geom_line(size=2) +
  geom_smooth() +
  ggtitle("Porównanie odchylenia standardowego ceny Warszawy i Gdańska") +
  theme(plot.title = element_text(hjust = 0.5))
vis_ex_2
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

Na bazie obserwacji dwóch przedstawionych zestawień należy zauważyć, że największe odchylenia cen między miastami przypadały w okresie, gdy ceny różniły się o niecałe 2000 złotych za metr kwadratowy w okresie stagnacji rynkowej zauważonej w poprzednich badaniach. Wówczas ceny ofertowe w Warszawie na rynku wtórnym utrzymywały stabilną, relatywnie wysoką cenę, zaś dopiero w ostatnich 5 latach, odpowiedniki cenowe w Gdańsku zdecydowanie wzrosły, wyrównując tym samym wyniki osiągane w stolicy. W ostatnich latach Gdańsk zyskał na popularności zawdzięczając ten ewenement szeregowi czynników takich jak ekologia, rozwój infrastruktury czy stabilna polityka samorządowa. Być może podobne elementy w przyszłości posłużą do oszacowania odpowiednich predykcji w analogicznych przypadkach.

0.5.4 Kształtowanie przeciętnej ceny transakcyjnej na rynku pierwotnym we wszystkich miastach w Polsce w ujęciu rocznym

Cena transakcyjna nierzadko różni się od ofert przedstawianych przez deweloperów. Wynika to przede wszystkim z możliwości negocjacyjnych obydwu stron, planowanej rozbudowy infrastruktury czy potencjalnego dostępu do obiektów inwestycyjnych czy obiektów niosących ze sobą pożytek publiczny. Niniejsze zestawienie zostało przygotowane w formie boxplot - narzędzia przedstawiającego nie tylko kształtowanie się średniej ceny rocznej, ale przedstawienie wahań wewnątrz podokresów w formie rozproszonej ceny względem “pudełek” oraz ich wielkości. W tym celu przygotowano odpowiednią ramkę danych uwzględniającą jedynie ceny średnie wszystkich rynków wraz z kwartalną datą obserwacji.

rpo_mean <- rpo$mean
rpt_mean <- rpt$mean
rwo_mean <- rwo$mean
rwt_mean <- rwt$mean
av_price <- data.frame(rpo_mean, rpt_mean, rwo_mean, rwt_mean, ROK)
head(av_price)

Wyniki przykładu, jakim są ceny transakcyjne dotyczące rynku pierwotnego przedstawiono na wykresie:

vis_ex_3 <- ggplot(data=av_price, aes(x=ROK, y=rpt_mean, colour=ROK)) +
  geom_boxplot(size=0.5, alpha=0.5) +
  geom_jitter() +
  xlab("Rok") +
  ylab("Przeciętna cena transakcyjna na rynku pierwotnym") +
  ggtitle("Kształtowanie przeciętnej ceny mieszkań w ujęciu rocznym w Polsce") +
  theme(plot.title = element_text(hjust = 0.5))
vis_ex_3

Należy zauważyć zasadniczą wadę wykresu w postaci niepełnych wartości dwóch okresów. Dane zebrane na potrzeby raportu uwzględniają dwa lata, w których przedstawienie kwartalnych cen jest niepełne - rok 2006 zawierał jedynie dwa ostatnie kwartały, zaś ostatni badany okres - trzy. Interesującą obserwacją jest rok 2007, czyli moment zmiany władzy w Polsce po wielomiesięcznych kryzysach pośrednio związanych także z rynkiem nieruchomości, co przekłada się na wielkość pudełka oraz wąsów w tym okresie. Kolejne lata niosły ze sobą względnie stabilne (w odniesieniu do rozproszenia pomiędzy kwartałami) ceny. Istotne wahania międzykwartałowe zauważa się od początku 2017 roku, gdy międzykwartylowe wartości zaczynają się od siebie regularnie oddalać. Wynika to z gwałtownego i regularnego wzrostu cen przeciętnych, co zaobserwowano także we wcześniejszej części pracy.

Dla pełniejszego obrazu, ten trend (widoczny także na pozostałych rynkach) pokazano na przykładzie gdańskich cen transakcyjnych na rynku wtórnym:

vis_ex_4 <- ggplot(data = rwt, aes(x=date, y=Gdańsk)) +
  geom_area(aes(fill=ROK)) +
  geom_smooth(alpha=2.5, color="Black", size=2) +
  xlab("Rok") +
  ylab("Cena za metr kwadratowy") +
  ggtitle("Przeciętna cena transakcyjna na rynku wtórnym w Gdańsku") +
  theme(plot.title = element_text(hjust = 0.5))
vis_ex_4
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

Widoczna jest zarówno tendencja wzrostowa, którą należy także odnieść do wcześniejszego zestawienia z Warszawą jak kształtowanie ceny pomiędzy kwartałami.

0.5.5 Kształtowanie cen 6 najzamożniejszych miast z wyłączeniem Warszawy

Jak wspomniano, stołeczne miasto w badanym okresie charakteryzowało się najwyższą ceną w przeliczeniu za metr kwadratowy na wszystkich rynkach. Interesującym wydaje się, na ile pozostałe, powszechnie popularne destynacje mieszkaniowe plasowały się względem średniej. Miasta zostały arbitralnie wybrane przez instytucję, która zapewniła dostęp do danych, czyli NBP. Wśród nich znalazły się Gdynia, Gdańsk, Kraków, Łódź, Poznań oraz Wrocław. Wyniki przedstawiono na poniższym wykresie:

kolory <- c("Gdynia" = "Red", "Kraków" = "Purple", "Gdańsk" = "DarkBlue", "Łódź" = "DarkGreen", "Poznań" = "DarkRed", "Wrocław" = "Grey")

vis_ex_5 <- ggplot(data = rpo, aes(x=date, y=mean), color="Black", size=1.3) +
  geom_line(aes(x=date, y=Gdynia, color = "Gdynia")) +
  geom_line(aes(x=date, y=Kraków, color= "Kraków")) +
  geom_line(aes(x=date, y=Gdańsk, color = "Gdańsk")) +
  geom_line(aes(x=date, y=Łódź, color = "Łódź")) +
  geom_line(aes(x=date, y=Poznań, color = "Poznań")) +
  geom_line(aes(x=date, y=Wrocław, color = "Wrocław")) +
  geom_jitter() +
  xlab("Rok") +
  ylab("Cena ofertowa na rynku pierwotnym") +
  ggtitle("Zestawienie cen ofertowych w 6 miastach względem średniej") +
  theme(plot.title = element_text(hjust = 0.5)) +
  labs(color = "Legenda")
scale_color_manual(values = kolory)
## <ggproto object: Class ScaleDiscrete, Scale, gg>
##     aesthetics: colour
##     axis_order: function
##     break_info: function
##     break_positions: function
##     breaks: waiver
##     call: call
##     clone: function
##     dimension: function
##     drop: TRUE
##     expand: waiver
##     get_breaks: function
##     get_breaks_minor: function
##     get_labels: function
##     get_limits: function
##     guide: legend
##     is_discrete: function
##     is_empty: function
##     labels: waiver
##     limits: Gdynia Kraków Gdańsk Łódź Poznań Wrocław
##     make_sec_title: function
##     make_title: function
##     map: function
##     map_df: function
##     n.breaks.cache: NULL
##     na.translate: TRUE
##     na.value: grey50
##     name: waiver
##     palette: function
##     palette.cache: NULL
##     position: left
##     range: <ggproto object: Class RangeDiscrete, Range, gg>
##         range: NULL
##         reset: function
##         train: function
##         super:  <ggproto object: Class RangeDiscrete, Range, gg>
##     rescale: function
##     reset: function
##     scale_name: manual
##     train: function
##     train_df: function
##     transform: function
##     transform_df: function
##     super:  <ggproto object: Class ScaleDiscrete, Scale, gg>
vis_ex_5

Niemal wszystkie z sześciu wybranych miast znajdowały się ponad średnią (czarne punkty na wykresie) przez większą część badanego okresu. Oznacza to, że w podanym ujęciu przeciętne ceny ofertowe na rynku pierwtonym były większe niż pozostałych miast. Wyjątkiem niniejszego zestawienia jest Łódź, która niemal cały okres znajdowała się pod linią przeciętnej ceny. Można zatem wnioskować, że pozostałe z wybranych miast w dużym stopniu przyczyniają się do kształtowania przeciętnej ceny ofertowej na rynku pierwotnym.

0.5.6 Porównanie cen rynku mieszkaniowego w Warszawie

Ostatnim zestawieniem przygotowanym na potrzeby raportu jest zestawienie porównawcze przeciętnych cen mieszkaniowych w najzamożniejszym mieście pod tym względem - Warszawie. Porównanie zostało przeprowadzone na wszystkich rynkach. W tym celu utworzono nową ramkę danych na potrzeby zestawienia oraz wykorzystano pakiet “gridExtra”, by przedstawić wyniki w jednym oknie.

Poniższy wykres przedstawia porównanie wszystkich rynków:

library(gridExtra)
## 
## Dołączanie pakietu: 'gridExtra'
## Następujący obiekt został zakryty z 'package:dplyr':
## 
##     combine
W_rpo <- rpo$Warszawa
W_rpt <- rpt$Warszawa
W_rwo <- rwo$Warszawa
W_rwt <- rwt$Warszawa

Warsaw <- data.frame(date, W_rpo, W_rpt, W_rwo, W_rwt)



p1 <- ggplot(data = Warsaw, aes(x=date, y=W_rpo)) +
  geom_area(aes(x=date, y=W_rpo), alpha=0.5, color="Red", fill="Red") +
  ylab("C. ofert., r. pierwotny") +
  xlab("Czas")
p2 <- ggplot(data = Warsaw, aes(x=date, y=W_rpo)) +
  geom_area(aes(x=date, y=W_rpt), alpha=0.5, color="Blue", fill="Blue") +
  ylab("C. trans., r. pierwotny") +
  xlab("Czas")
p3 <- ggplot(data = Warsaw, aes(x=date, y=W_rpo)) +
  geom_area(aes(x=date, y=W_rwo), alpha=0.5, color="DarkGreen", fill="DarkGreen") +
  ylab("C. ofert., r. wtórny") +
  xlab("Czas")
p4 <- ggplot(data = Warsaw, aes(x=date, y=W_rpo)) +
  geom_area(aes(x=date, y=W_rwt), alpha=0.5, color="Grey", fill="Grey") +
  ylab("C. trans., r. wtórny") +
  xlab("Czas")
  


Wars_comp <- grid.arrange(p1, p2, p3, p4, top = "Porównanie cen mieszkań w Warszawie")

Należy zwrócić uwagę na kilka tendencji, które odnoszą się także do pozostałych miast w Polsce, gdyż mimo specyfiki cenowej Warszawy, należy uznać przykład miasta za reprezentatywny wobec społeczności wielkomiejskiej w Polsce:

  • Ceny transakcyjne są przeważająco niższe na rynku transakcyjnym w porównaniu do odpowiedników ofertowych.

  • Większa rozpiętość cenowa zauważalna jest na rynku wtórnym pomiędzy ofertą a faktyczną ceną.

  • Krzywa cenowa na rynku wtórnym jest bardziej płaska, co oznacza, że na tym rynku następują mniejsze wahania.

  • Tendencja wzrostowa jest podobna na wszystkich rynkach.

Kształtowanie przeciętnych cen transakcyjnych wiąże się z ograniczeniami w postaci pominięcia trendów sezonowych, lukratywnych inwestycji nowych deweloperów czy kryzysów społecznościowych (migracje, wahania demograficzne w dłuższym okresie). Niemniej jednak, wartości przekazane z zestawienia stanowią istotny obraz kształtowania cen na rynkach nieruchomościowych.

0.6 Podsumowanie wyników - analiza końcowa

Jak wspomniano, w zakresie raportu badanie cen jest ograniczone przez szereg czynników. Autorzy przyjęli jednak, że same wartości stanowią pewnego rodzaju odzwierciedlenie rynku nieruchomości w Polsce, a na tej podstawie należy wysunąć kilka wniosków.

Przede wszystkim, rynek ukierunkowany jest na tendencję wzrostową. Zakres danych ogranicza możliwość określenia szacunku przyczynowego takiego stanu rzeczy, jednak dopuszczalne hipotezy wiążą się z otoczeniem ekonomicznym, jak rosnąca inflacja (choć dotyczy ona końcowych lat) oraz bańka spekulacyjna. Należy jednocześnie uwzględnić czynniki społeczne, takie jak moda na posiadanie własnego lokum oraz coraz popularniejsze źródło dodatkowego dochodu w postaci wynajmu kolejnego mieszkania.

Kolejnym wnioskiem jest zestawienie cenowe wśród najbogatszych miast. Jak pokazano, wahania odchyleń standardowych są zauważalne w coraz mniejszym stopniu. Potwierdzał to także wykres, który zestawiał 6 najzamożniejszych miast, gdzie w ostatnich okresach, przeciętne ceny zaczęły coraz mniej się różnić. Oznacza to zarówno wzrost poziomu życia w wielkich miastach w Polsce jak i spadek znaczenia Warszawy jako wyznacznika tego poziomu.

Ostatni wniosek wiąże się ze zwiększającą się rozpiętością pomiędzy cenami ofertowymi oraz transakcyjnymi na rynkach. Narastająca tendencja może wskazywać na mechanizmy spekulatywne w podażowej części rynku, a więc deweloperów oraz właścicieli mieszkań na sprzedaż. Rynki są ze sobą ściśle związane, zatem narastające spekulacje odnoszą się wzajemnie do siebie, co tworzy niebezpieczeństwo kryzysu i załamania się rynku nieruchomości w przewidywalnym okresie.

Badanie było ograniczone do danych cenowych. Istotnym wzbogaceniem mogłoby być uwzględnienie mierzalnych aspektów ekonomicznych, takich jak przeciętne wynagrodzenie, inflacja czy też dane związane z rynkiem najemczym. Nie dokonywano także większych obliczeń cenowych ze względu na ograniczony zakres raportu, przykładowym rozwinięciem mogłoby być zbadanie jednego miasta lub porównanie dwóch względem modelu rynkowego.