/ Berlin

Bayessche Hauspreise in Berlin

TL; DR: Lage ist ein sehr wichtiger Faktor in der Vorhersage von Hauspreisen und die Bezirke Mitte und Prenzlauer Berg sind besonders teuer.

Wie teuer ist eigentlich eine Immobilie in Berlin? Jeder hat das Gefühl, dass Wohneigentum in Berlin heutzutage teuer ist, aber wie teuer genau? Und welche Bezirke sind besonders teuer? In dieser Analyse möchte ich auf Basis unserer Daten analysieren, wie sich die Kaufpreise in den Berliner Bezirken unterscheiden.

Da es hier nicht nur darum geht die Kaufpreise einzelner Immobilien vorherzusagen, sondern viel mehr darum herauszufinden, welche Bezirke besonders teuer sind, werde ich mich auf ein einfaches lineares Model beschränken, dass die Kaufpreise anhand der Wohnfläche und der Postleitzahl vorhersagt. Dies hat zwar den Nachteil, dass die Vorhersage eine geringere Genauigkeit haben, aber dafür erhalten wir ein einfach interpretierbares Model. Aber später mehr zum Modell, schauen wir uns erstmal die Daten an.

Explorative Analyse der Daten

Zum Visualisieren der Postleitzahlenbezirke benutzen wir ShapeFiles (zum Download-Link). Shapefiles beinhalten, einfach gesagt, die Form der einzelnen Postleitzahlenbezirke. Die hier benutzen Shapefiles beinhalten alle Postleitzahlen in Deutschland, wir beschränken uns hier allerdings nur auf die Postleitzahlen in Berlin.

Um etwas Schreibarbeit zu sparen, gruppieren wir bestimmte Postleitzahlen zu ihren Ortsteilen zusammen:

mitte <- c("10115", "10117", "10119", "10178", "10179")
friedrichshain <- c("10243", "10245", "10247", "10249")
prenzlberg <- c("10405", "10407", "10409", "10435", "10437", "10439")
kreuzberg <- c("10961", "10963", "10965", "10967", "10997", "10999", "10969")
neukoelln <- c("12043", "12045", "12047", "12049", "12051", "12053", "12055", "12057", "12059")
wedding <- c("13347", "13349", "13351", "13353", "13357", "13359", "13407", "13355")
moabit <- c("10551", "10553", "10555", "10557", "10559", "13353")

Wir filtern alle Immobilien raus, die eine Wohnfläche kleiner oder gleich 0 haben und berechnen außerdem den Gesamtkaufpreis als Summe der Herstellungs- und Modernisierungskosten, sowie des Kaufpreises und Grundstückkaufpreises (wenn jeweils vorhanden).

df <- df %>% 
  filter(gesamtwohnflaeche > 0) %>%
  mutate_at(c("herstellung", "grundstueckskaufpreis", 
              "kaufpreis", "modernisierung"), funs(replace(., is.na(.), 0))) %>%
  mutate(gesamt_kaufpreis = herstellung + grundstueckskaufpreis + kaufpreis + modernisierung,
         qm_preis =  gesamt_kaufpreis / gesamtwohnflaeche )
 [1] "Anzahl Daten: 9802"

Die Immobilien wurden alle im Zeitraum 2016 bis jetzt zum Verkauf angeboten. Nicht unbedingt alle Immobilien wurden tatsächlich auch gekauft, da die Daten auch Anträge enthalten können, die zumindest von der Bank abgelehnt worden sind. Dies kann dazu führen, dass der Kauf eventuell nicht zustande kam. Es kann aber trotzdem davon ausgegangen werden, dass die Immobilien für denselben (oder ähnlichen) Preis verkauft wurden.

ggplot(df, aes(x=angenommendatum, y=..density..)) +
  geom_histogram(binwidth = 90) +
  scale_y_continuous(labels=scales::percent_format()) +
  labs(x="", y="", title="Verteilung der Immobilienanträge") +
  theme_minimal()

Verteilung der Immobilienanträge

Intern wird die Firmenadresse gerne als Testfall genommen, diese müssen vor weiteren Analysen entfernt werden. Andere Testfälle werden häufig mit der Musterbank abgeschlossen, dies lässt sich ebenfalls einfach herausfiltern.

df <- df %>%
  filter(strasse != "Klosterstraße" &
           !str_detect(produktanbieterid, "MUSTER") &
           !(hausnummer==71 & plz=="10179"))

Für eine lineare Regressionsanalyse sind insbesondere Outlier sehr problematisch. Wir werfen daher einen kurzen Blick auf die Verteilungen der Variablen:

df %>% 
  select(gesamt_kaufpreis, gesamtwohnflaeche, qm_preis, baujahr) %>%
  GGally::ggpairs()

Pairs plot

Sowohl Gesamtkaufpreis als auch Gesamtwohnfläche haben sehr rechts-schiefe Verteilungen, dass heißt die Verteilungen haben lange Ausläufer nach rechts. Konkret heißt das, dass es ein paar Immobilien mit sehr hohem Kaufpreis beziehungsweise hoher Gesamtwohnfläche gibt. Beide Variablen korrelieren sehr stark miteinander. Für diese sehr hohen Werte gibt es zwei mögliche Erklärungen: Es kann sich um tatsächlich große, teure Häuser (vielleicht Villen in Dahlem?) handeln. Die andere Möglichkeit, und für uns sehr viel ungünstiger, sind Datenfehler, wie falsch eingegeben oder ähnliches. Die Eigentumswohnung in Köpenick von einer Grundstücksgröße von 6 Millionen Quadratmetern scheint beispielsweise einer dieser Datenfehler zu sein. Für ein lineares Modell können beide Outlier schwierig sein. Einmal gibt es für diese Datenbereiche nur sehr wenig Daten (per Definition von Outliern), und zweitens ist davon auszugehen, dass der Kaufpreis von Immobilien mit sehr großer Wohnfläche nicht mehr einem einfachen linearen Modell folgt. Es scheint beispielsweise sinnvoll anzunehmen, dass sehr große Objekte zu einem niedrigeren Quadratmeterpreis führen. Auch bei Visualisierungen sind solche Outlier immer etwas problematisch, deswegen werde ich mich in dieser Analyse auf die eher "durchschnittlichen" Immobilien konzentrieren.

Immobilien mit

  • Grundstücksgrößen größer als 5 000 Quadratmeter
  • Gesamtwohnflächen größer als 500 Quadratmeter oder
  • Gesamtkaufpreise größer als 3 Millionen €

wurden herausgenommen.

df.m  <- df %>%
  filter(grundstuecksgroesse < 5e4 &
           gesamtwohnflaeche < 500 &
           gesamt_kaufpreis < 3e6) 
 [1] "Anzahl herausgenommene Daten: 1027"

 [1] "In Prozent: 10.9%"

Wie verteilen sich die übrigen Fälle über die Postleitzahlenbezirke hinweg?

Anzahl Faelle

Die meisten Postleitzahlbezirke haben etwa 30-40 Fälle, nur Friedrichshain hat mit jeweils etwa 100 bis 200 Fällen sehr viel mehr.

Wie hoch ist der durchschnittliche Gesamtkaufpreis in den einzelnen Bezirken?

Durchschnittspreise

Ganz unten links auf der Karte kann man den Rand des Villenviertel Dahlem (PLZ 14195) sehen, mit Durchschnittspreisen von 664.000€ (Median). Die Gegend rund um das KaDeWe (PLZ 10789) ist mit durchschnittlichen Kaufpreisen von 772.000€ ebenfalls ziemlich teuer.

Man muss hierbei bedenken, dass wir unter Umständen sehr kleine Eigentumswohnungen mit großen Villen vergleichen. Einen besseren Vergleich erhalten wir, wenn wir uns die durchschnittlichen Quadratmeterpreise anschauen:

Quadratmeterpreise

Die teuersten Durchschnittsquadratmeterpreise sind in Mitte-Tiergarten (10557) und im Wedding (13355) zu finden. Wedding hat allerdings weniger Fälle als der Durchschnitt, könnte daher also stärker verzerrt sein durch einzelne Fälle.

Das Modell

Da Postleitzahlen eine kategorische Variable mit sehr vielen Ausprägungen ist (nur in Berlin allein gibt es mehr als 100 Postleitzahlen), ist es oft sehr schwierig diese sinnvoll in ein Modell zu integrieren. Um kategorische Variablen in einen numerischen Wert umzuwandeln, wird in Machine Learning häufig One-Hot Encoding genutzt. In einem One-Hot-Encoding wird für jeden Wert, den die kategorische Variable annehmen kann eine Dummy-Variable erschaffen, die entweder 0 oder 1 ist. Ist eine Immobilie aus der Postleitzahl 10179 hätte die Dummy-Variable 10179 den Wert 1 und alle anderen Dummy-Variablen würden den Wert 0 annehmen.
Das heißt, für jede Postleitzahl würden wir eine Variable hinzufügen. In unserem Datenset würde dies zu mehr als 100 zusätzlichen Variablen führen. Dies wird schnell rechenaufwändig und verschlechtert außerdem häufig die Modellqualität.

Zusätzlich ist davon auszugehen, dass sich der Quadratmeterpreis in den unterschiedlichen Bezirken stark unterscheidet. Das heißt also, dass die Variable Gesamtwohnfläche in den verschieden Postleitzahlbezirken einen anderen Einfluss auf den Kaufpreis hat. In Prenzlauer Berg würde beispielsweise ein Unterschied von einem Quadratmeter zu einer sehr viel stärkeren Änderung im Preis führen als in Lichtenberg. Eine Möglichkeit wäre hier, für jede Postleitzahl ein Modell zu berechnen. Dies ist insofern ungünstig, da manche Bezirke sehr viel weniger Daten haben als andere und wir außerdem davon ausgehen, dass sich der Einfluss der Gesamtwohnfläche in den einzelnen Postleitzahlbezirken zwar unterscheiden, aber auch nicht zu stark. Wir würden erwarten, dass in Prenzlauer Berg der Einfluss der Gesamtwohnfläche höher ist als in Lichtenberg, aber in beide Postleitzahlbezirken hätte Gesamtwohnfläche natürlich einen positiven Einfluss (größere Gesamtwohnfläche = höherer Preis). Für solche Variablen eignet sich sehr gut ein hierarchisches Modell (die besonders gut mit Bayesschen Methoden funktionieren). In einem hierarchischen Modell nehmen wir an, dass die Einflussfaktoren der einzelnen Postleitzahlen von einander abhängen.
Statistisch gesehen heißt dies, das die Einflussfaktoren (korrekt Koeffizienten genannt) von derselben Verteilung stammen. Prenzlauer Berg würde dann beispielsweise eher von den höheren Perzentilen der Verteilung stammen und Lichtenberg eher von den unteren.

Im Folgenden fitten wir ein solches hierarchisches Regressions Modell, dass den Kaufpreis anhand der Wohnfläche per Postleitzahl vorhersagt. Die Formel ist

$$\text{Kaufpreis} \sim \alpha_{[plz]} + \beta_{[plz]}\text{Wohnfläche}$$

Wir nehmen also eine lineare Relation zwischen dem Kaufpreis und der Wohnfläche an. $\alpha$ ist hier der $y$-Achsenabschnitt, im englischen Intercept genannt, und $\beta$ ist der Koeffizient, der den Einflussfaktor der Gesamtwohnfläche quantifiziert. $\beta$ gibt die Steigung des linearen Modells an. Für jede Postleitzahl wird ein $\alpha$ und ein $\beta$ berechnet.

Zum Berechnen des Modells benutze ich das Package rstanarm, welches ein sehr einfaches Interface für lineare Modelle bereitstellt. Als Backend wird die Modelling-Sprache Stan benutzt, aber rstanarm erlaubt es uns, Bayessche Modelle in der gewohnten R Formel Sprache von lm() zu spezifizieren.

Wir transformieren den Gesamtkaufpreis auf Kaufpreis in 100.000€ um so kleinere Koeffizienten zu erhalten. Für die Koeffizienten benutzten wir dann folgende Prior Verteilungen:

$$\begin{align*}
\alpha & \sim \text{Normal}(3, 1) \\
\beta &\sim \text{Normal}(0, 0.5)
\end{align*}$$

Da die Gesamtwohnfläche normalisiert und zentriert wurde, entspricht der Intercept $\alpha$ dem Kaufpreis einer Immobilien mit durchschnittlicher Wohnfläche (~104m²). Ohne die Daten gesehen zu haben, würde ich erwarten, dass dieser Wert mindestens zwischen 100.000€ und 500.000€ liegt und habe daher den Prior $\text{Normal}(3,1)$ gewählt. Mit einer ähnlichen Argumentation kommen wir zu dem Prior für den Steigungsparameter: Eine Änderung der Wohnfläche um etwa 50m² (eine Standardabweichung) sollte zu einer Preisänderung von etwa 50.000€ bis zu 150.000€ führen. Ein etwas weiterer Prior führte zu vergleichbaren Ergebnissen, das Modell scheint hier also recht stabil zu sein.

df.model <- df.m %>% 
  select(gesamtwohnflaeche, baujahr, gesamt_kaufpreis, 
         objektart, plz) %>%
  replace_na(list(baujahr=median(df$baujahr, na.rm=T))) %>%
  mutate_at(vars(gesamtwohnflaeche, baujahr), funs(as.numeric(scale(., scale = T)))) %>%
  mutate(plz = factor(plz),
         pooled_plz = plz %>% 
           fct_collapse(wedding = wedding,
                        kreuzberg = kreuzberg,
                        neukoelln = neukoelln),
         gesamt_kaufpreis = gesamt_kaufpreis / 100000) 
mod <-   stan_lmer( gesamt_kaufpreis ~  gesamtwohnflaeche + 
          (1 + gesamtwohnflaeche | pooled_plz)  ,
          data=df.model,
          prior_intercept=normal(location=3, scale=1),
          prior=normal(location=0, scale=0.5)) 

Evaluation des Modells

Das rstanarm liefert mit shinystan eine einfache und praktische Möglichkeit, um zu überprüfen, ob das Modell konvergiert ist. Shinystan ist ähnlich wie Tensorboard nur für Bayessche Modelle. Anders als bei Tensorboard sehen wir zwar nicht das Live-Training, aber können das Modell nach dem fitten auf Herz und Nieren untersuchen. Zusätzlich zu Checks und Diagnostiken zur Konvergenz des Modells, gibt es auch Predictive Checks, die Einblicke geben, wie gut das Modell die echten Daten abbildet.

launch_shinystan(mod)

Shinystan-App

Ich werde hier nicht weiter auf die unterschiedlichen Diagnostiken und Checks eingehen, es sei hier nur gesagt, dass in diesem Fall alle Modell-Diagnostiken gut aussehen und wir davon ausgehen können, das unser Modell konvergiert ist. Erste Checks zur Qualität der Vorhersage sehen ebenfalls vielversprechend aus. Dies werden wir in den nächsten Plots genauer untersuchen.

Da wir nur schwerig alle Koeffizienten jeder Postleitzahl manuell untersuchen können, beschränken wir uns hier auf einige beispielhafte Postleitzahlen. Im folgenden plotten wir die echten Fälle (in schwarz) über die Vorhersage (jeweils in Farbe). Die Credibility Intervals von 50% und 80% sind jeweils in leicht transparenten Farben geplottet. Eine gute Vorhersage würde also bedeuten dass mindestens 80% der Punkte innerhalb des Farbringes sind.

Vergleich des Modells für verschiedene PLZ

Per Augenmaß sehen die Vorhersagen erstmal ganz gut aus. Ein paar Dinge, die auffallen:

Im Modell habe ich die Postleitzahlen für Kreuzberg, Neukölln und Wedding jeweils zusammengefasst, da die Postleitzahlen in diesen Gegenden teilweise nur sehr wenige Daten hatten. Die unteren drei Graphiken basieren also auf den Daten von jeweils mehreren Postleitzahlen.
Es scheint so, als ob dies auch zu einer größeren Preisvarianz in den zusammengefassten Daten führt.

In Neukölln gibt es außerdem zwei Immobilien mit mehr als 350m² Wohnfläche, deren Kaufpreis unter der Vorhersage des Modells liegt. Diese zwei Ausreißer führen dazu, dass die Steigung für Neukölln nach unten gedrückt wird. Da viele dieser sehr großen Immobilien Mehrfamilienhäuser sind, könnte das Modell hier verbessert werden, wenn man diese Variable (Objektart: Wohnung, Einfamilienhaus, Zweifamilienhaus, Mehrfamilienhaus) ins Modell hinein nimmt.

Für Mitte (10119) sind die Vorhersagen auch für große Wohnflächen relativ gut und die hohe Steigung bestätigt, was man sich schon gedacht hat: Mitte ist teuer. Die Postleitzahl 10178, ebenfalls in Mitte, hat dagegen eine geringere Steigung, aber die breiteren Credibility Intervals zeigen auch eine größere Unsicherheit im Modell: Die meisten Immobilien dieser Postleitzahl sind mit unter 150m² relativ klein und dementsprechend ist die Unsicherheit hoch für größere Wohnflächen.

Der Intercept in unserem Modell ist äquivalent zu dem Kaufpreis für eine durchschnittliche Immobilie (mit etwa 104m²). Diesen Wert können wir nun über alle Postleitzahlen hinweg vergleichen:

Durchschnittspreise-Intercept

Dieser Grundpreis unterscheidet sich vom durchschnittlichen Kaufpreis insofern, dass sollte ein Bezirk überdurchschnittlich große oder eher kleine Wohnungen haben, dann steigt, beziehungsweise sinkt, der durchschnittliche Kaufpreis ebenfalls. Während im Bild vorhin nur Dahlem mit seinen Villen und die Gegend um das KaDeWe als besonders teuer auffielen, sind in diesem Bild vor allem die Bezirke in Mitte und Prenzlauer Berg auffällig teuer. Während wir also vorhin große Villen mit kleinen Eigentumswohnungen verglichen haben, vergleichen wir hier, wie teuer dieselbe Wohnung in verschiedenen Bezirken wäre. Wir erhalten also den Preis für die Lage.

Quadratmeterpreise-Steigung

Die Steigung des Modells gibt an, wie viel teurer eine Immobilie wird, wenn sie einen Quadratmeter größer wird. Die Steigung ist also der Preis per Quadratmeter. Auch hier erhalten wir ein leicht anderes Bild als vorher, da wir nun den Preis der Lage durch den Intercept schon einberechnet haben.

Man beachte, dass Kreuzberg, Neukölln und Wedding zu jeweils mehreren Postleitzahlen zusammengefasst worden sind und daher über die Postleitzahlen hinweg die gleiche Estimates haben. Es darf außerdem nicht vergessen werden, dass unser Modell nicht gleich sicher ist für alle Postleitzahlen. Zum Beispiel in Mitte (10178) war sich unser Modell ziemlich unsicher, es kann also gut sein, dass sowohl der Grundpreis als auch der Preis per Quadratmeter höher sind als von unserem Modell angegeben.

Fehler des Models

Der $R^2$ des Modells liegt bei

bayes_R2(mod) %>% mean
 [1] 0.7139335

Das heißt, etwa 70% der Varianz des Kaufpreises wird durch unser Modell erklärt. Die Wohnfläche und Lage einer Immobilie bestimmen also fast vollkommen den Kaufpreis.

Wir haben oben schon gesehen, dass wir insbesondere große Immobilien im Preis häufig überschätzen. Im folgenden analysieren wir, wie hoch die durchschnittliche prozentuale Abweichung des echten Kaufpreises zur Vorhersage ist. Wir benutzen hierzu den MAPE (mean average percentage error).

MAPE

Insbesondere die Neuköllner Postleitzahlen haben einen hohen Fehler. Es scheint, dass ein Pooling der Neuköllner Postleitzahlen das Modell hier eher verschlechtert hat. Andere Postleitzahlen, wie beispielsweise 10178 in Mitte, haben dagegen einen relativ geringen durchschnittlichen prozentualen Fehler von weniger als 20%.

Wie gut performt unser Modell verglichen mit einem Modell, in dem wir nur die Gesamtwohnfläche betrachten? Also ein Modell, in dem wir die Lage vollkommen ignorieren?

alternative <- stan_glm( gesamt_kaufpreis ~  gesamtwohnflaeche   ,
          data=df.model,
          prior_intercept=normal(location=3, scale=1),
          prior=normal(location=0, scale=0.5)) 

Wieviel Varianz des Kaufpreises wird durch das alternative Modell erklärt?

bayes_R2(alternative) %>% mean
 [1] 0.519395

Nur 52%.
Dies ist sehr viel schlechter als die 70% für das hierarchische Modell. Lage ist also ein wichtiger Faktor für den Preis einer Immobilie und sollte bei der Vorhersage von Kaufpreisen nicht ignoriert werden.

Für welche Bezirke perfomt das alternative Modell schlechter?

Alternatives Modell

Verglichen mit dem hierarchischen Modell ist der Fehler des alternativen Modells sowohl ingesamt als auch für die einzelnen Postleitzahlen jeweils höher.

Interessanterweise performt das alternative Modell vor allem für umliegende Bezirke sehr viel schlechter. Das Modell überschätzt die Preise von Immobilien in günstigeren Lagen. Dies lässt sich erklären, wenn man sich erinnert, wie die Verteilung der Immobilien in diesen Daten über die Postleitzahlenbezirke ist: Es gibt sehr viele Daten über Immobilien in Friedrichshain und Prenzlauer Berg und eher wenig Daten vom Wedding, Kreuzberg, Neukölln und den Randbezirken. Friedrichshain und Prenzlauer Berg werden daher vom einfacheren Alternativ-Modell immer noch recht gut vorhergesagt, aber Gegenden wie Wedding, die günstiger als Friedrichshain sind, schneiden dadurch schlechter ab im Modell.

Ein weiterer wichtiger Faktor, der in beiden Modell nicht berücksichtigt wird, ist die Entwicklung der Preise über Zeit. Wir betrachten nur Immobilien der letzten zwei Jahre, aber in manchen Bezirken sind die Preise durchaus stark gestiegen in dieser Zeit. Es wäre spannend zu untersuchen, in welchen Bezirken die Preise stärker oder schwächer angestiegen sind. Aber dies ist eine andere Analyse.