Kunden zu halten ist häufig günstiger als neue Kunden zugewinnen. Deshalb ist für viele Firmen die Analysen von Kündigungsverhalten wichtig. In diesem Beispielsdatensatz aus der Telekommunikationsbranche gibt es 21 Variablen zum Kündigungsverhalten sowie zum sozio-ökonomischen Status und den Vertragsmodalitäten von 7043 Kunden. 27% der Kunden in dem Datensatz haben ihren Vertrag gekündigt.
Die explorative Datenanalyse zeigt teilweise bereits deutliche Unterschiede im Kündigungsverhalten zwischen Kunden mit verschiedenen sozio-ökonomischen Status oder unterschiedlichen Vertragsmodalitäten. Insbesondere kündigen Neu-Kunden und Kunden mit monatlicher Vertragsdauer relativ häufig. Kunden mit Partnern oder Kindern kündigen seltener, Rentner hingegen kündigen vergleichsweise häufig.
Der Datensatz besteht aus 7043 Beobachtungen für 21 Variablen.
Die Daten wurden am 1.2.2016 von community.watsonanalytics.com heruntergeladen. Leider gibt es keine vollständige Dokumentation mit Beschreibungen der einzelnen Variablen. Ich gehe also etwa davon aus, dass die bisherige Vertragsdauer (tenure) in Monaten und die Gesamtgebühren (TotalCharges) in US Dollar angegeben sind.
Für die weitere Auswertung übersetzen wir zunächst die Ausprägungen ins Deutsche.
### Datenaufbereitung
# Classes sind schon richtig definiert, bis auf SeniorCitizen
my.data$SeniorCitizen<- factor(SeniorCitizen, labels = c("Nein", "Ja"))
# Übersetzung der Wertelabels
levels(my.data$Churn)[levels(Churn)=="No"] <- "Nein"
levels(my.data$Churn)[levels(Churn)=="Yes"] <- "Ja"
levels(my.data$Contract)[levels(Contract)=="Month-to-month"] <- "Monatlich"
levels(my.data$Contract)[levels(Contract)=="One year"] <- "1 Jahr"
levels(my.data$Contract)[levels(Contract)=="Two year"] <- "2 Jahre"
levels(my.data$gender)[levels(gender)=="Female"] <- "Frau"
levels(my.data$gender)[levels(gender)=="Male"] <- "Mann"
levels(my.data$Partner)[levels(Partner)=="No"] <- "Nein"
levels(my.data$Partner)[levels(Partner)=="Yes"] <- "Ja"
levels(my.data$Dependents)[levels(Dependents)=="No"] <- "Nein"
levels(my.data$Dependents)[levels(Dependents)=="Yes"] <- "Ja"
Im nächsten Schritt verschaffen wir uns einen Überblick über den Datensatz. Dabei geht es darum sich zum einen mit den Daten vertraut zu machen und zum anderen Ungereimtheiten in den Daten - etwa auf Grund von Eingabefehlern - zu finden.
## Fehlende Daten oder mögliche Eingabefehler
## Plausibilitätscheck
summary(my.data)
## customerID gender SeniorCitizen Partner Dependents
## 0002-ORFBO: 1 Frau:3488 Nein:5901 Nein:3641 Nein:4933
## 0003-MKNFE: 1 Mann:3555 Ja :1142 Ja :3402 Ja :2110
## 0004-TLHLJ: 1
## 0011-IGKFF: 1
## 0013-EXCHZ: 1
## 0013-MHZWF: 1
## (Other) :7037
## tenure PhoneService MultipleLines InternetService
## Min. : 0.00 No : 682 No :3390 DSL :2421
## 1st Qu.: 9.00 Yes:6361 No phone service: 682 Fiber optic:3096
## Median :29.00 Yes :2971 No :1526
## Mean :32.37
## 3rd Qu.:55.00
## Max. :72.00
##
## OnlineSecurity OnlineBackup
## No :3498 No :3088
## No internet service:1526 No internet service:1526
## Yes :2019 Yes :2429
##
##
##
##
## DeviceProtection TechSupport
## No :3095 No :3473
## No internet service:1526 No internet service:1526
## Yes :2422 Yes :2044
##
##
##
##
## StreamingTV StreamingMovies Contract
## No :2810 No :2785 Monatlich:3875
## No internet service:1526 No internet service:1526 1 Jahr :1473
## Yes :2707 Yes :2732 2 Jahre :1695
##
##
##
##
## PaperlessBilling PaymentMethod MonthlyCharges
## No :2872 Bank transfer (automatic):1544 Min. : 18.25
## Yes:4171 Credit card (automatic) :1522 1st Qu.: 35.50
## Electronic check :2365 Median : 70.35
## Mailed check :1612 Mean : 64.76
## 3rd Qu.: 89.85
## Max. :118.75
##
## TotalCharges Churn
## Min. : 18.8 Nein:5174
## 1st Qu.: 401.4 Ja :1869
## Median :1397.5
## Mean :2283.3
## 3rd Qu.:3794.7
## Max. :8684.8
## NA's :11
Es gibt nur wenige fehlende Werte bei TotalCharges und keine Auffälligkeiten (wie etwa negative Werte für Charges).
Mit den Befehlen
verschaffen wir uns einen weitergehenden Einblick in die Daten und können darüber schon einige interessante Einsichten in die Kunden gewinnen (Ergebnisse nicht angezeigt / auskommentiert. table() und prop.table() erstellen Tabellen mit Häufigkeitsverteilungen, summary() fasst eine numerische Variablen (oder alle Variablen eines Datensatzes wie hier) zusammen und hist() erstellt ein einfaches Histogram, um die Verteilung einer numerischen Variablen zu visualisieren. Sie sind alle R-nativ und benötigen keine zusätzlichen Bibliotheken. Für die Kommunikation ist die Darstellungsform zu krude, aber für die eigene Datenexploration sind diese Grundfunktionen sehr nützlich. Weiter unten erstellen wir ansprechendere Datenvisualisierungen mit ggplot.
### Deskriptive Statistik
# ### Explorative Datenanalyse
# ## Univariate Darstellungen
# barplot(table(Churn), main="Churn")
# # Churn nicht balanced
#
# layout(matrix(1:8, nc=2))
# barplot(table(gender), main="Gender")
# barplot(table(SeniorCitizen), main="Senior Citizen")
# barplot(table(Dependents), main="Dependents")
# barplot(table(PhoneService), main="Phone Service")
# barplot(table(MultipleLines), main="Multiple Lines")
# barplot(table(OnlineSecurity), main="Online Security")
# barplot(table(OnlineBackup), main="Online Backup")
# barplot(table(DeviceProtection), main="DeviceProtection")
# # Wenige Senior Citizens, wenige ohne PhoneService,
#
# layout(matrix(1:6, nc=2))
# barplot(table(TechSupport), main="Tech Support")
# barplot(table(StreamingTV), main="Streaming TV")
# barplot(table(StreamingMovies), main="Streaming Movies")
# barplot(table(Contract), main="Contract")
# barplot(table(PaperlessBilling), main="Paperless Billing")
# barplot(table(PaymentMethod), main="Payment Method")
# # Tech Support, Streaming TV, Streaming Movies hängt von Internet ab
# # Monatlicher Vertrag am häufigsten
#
# hist(MonthlyCharges, main="Monthly Charges")
# # Multimodale Verteilung für monthly charges
# hist(TotalCharges, main="Total Charges")
# # Schiefe Verteilung, wenige sehr hohe Werte
# #
# # Häufigkeitsverteilung in Prozentangaben
# prop.table(table(Churn))
# prop.table(table(gender))
# prop.table(table(Partner))
# prop.table(table(Dependents))
# prop.table(table(SeniorCitizen))
# prop.table(table(PhoneService))
# prop.table(table(InternetService))
# prop.table(table(Contract))
# summary(tenure)
# hist(tenure)
# cumsum(prop.table(table(tenure)))
# prop.table(table(PaperlessBilling))
# prop.table(table(PaymentMethod))
# # Die Variablen für Zusatzdienste (z.B. OnlineSecurity) hängen vom Basisdienst ab (InternetService)
# table(InternetService)
# table(OnlineSecurity)
# Kleinerer Datensatz für Internetkunden
my.data.internet<-subset(my.data, InternetService!="No")
my.data.internet<-droplevels(my.data.internet)
# prop.table(table(my.data.internet$OnlineSecurity))
# prop.table(table(my.data.internet$OnlineBackup))
# prop.table(table(my.data.internet$DeviceProtection))
# prop.table(table(my.data.internet$TechSupport))
# prop.table(table(my.data.internet$StreamingTV))
# prop.table(table(my.data.internet$StreamingMovies))
#
# # Gebühren
# summary(MonthlyCharges)
# hist(MonthlyCharges)
# summary(TotalCharges)
# hist(TotalCharges)
Neben der Variable für das Kündigungsverhalten (ja/nein) gibt es sozio-ökonomische Variablen (Geschlecht, Partner, Kinder, Rentner), zu dem bestehenden bzw. gerade gekündigten Vertrag (Vertragsdauer, Umfang) und zum Nutzungsverhalten (monatliche Gebühren, Kosten insgesamt). 27% der Kunden im Datensatz haben Ihren Vertrag gekündigt. Die Anzahl der Kunden mit und ohne Partner sowie die Aufteilung nach Geschlechtern ist ungefähr gleich. 30% der Kunden haben Kinder, 16% sind Rentner. 90% der Kunden beziehen einen Telefonanschluss über den Anbieter, fast 80% haben (auch) einen Internetanschluss abonniert. Die meisten Kunden mit Internetanschluss haben auch noch eine oder mehrere Zusatzleistungen bestellt. Dies sind Internetsicherheit (63%), technische Hilfe (63%), Geräteschutz (56%), Streaming TV (51%) und Streaming Filme (51%). Mit Abstand am meisten Kunden haben einen Vertragslaufzeit über einen Monat (55%), die anderen haben eine Vertragsdauer von einem Jahr (20%) oder zwei Jahren (25%). Die längste bisherige Vertragsdauer beträgt 72 Monate, der Durchschnitt liegt bei 32,4 Monaten. Relativ viele Kunden hatten nur eine sehr kurze Vertragsdauer. Bei etwa 10% der Kunden lag die Vertragsdauer bei einem Monat (oder weniger), 25% der Kunden hatten eine Vertragsdauer die weniger als 9 Monate lief. Die meisten Kunden beziehen digitale Rechnungen (59%) und zahlen mit einem digitalen Scheque (34%). Die monatliche Gebühren liegen im Schnitt bei 64,76 USD, sie reichen von 18,25 USD bis zu 118.50 USD. Die insgesamt gezahlten Gebühren liegen zwischen 18,80 USD und 8 685 USD (Durchschnitt: 2 283, Median: 1 397).
Für die weitere Analyse ist die Datenvisualisierung essentiell. Im Folgenden nutzen wir die Bibliothek ggplot, mit der sich eine Vielzahl von maßgeschneiderten Grafiken erstellen lässt. ggplot() nutzt eine universelle Sprache von Grafiken (“grammar of graphics”), um mit einer einheitlichen Syntax alle erdenklichen Grafiken erstellen zu können. Insbesondere sind dies die darzustellende Information / Variablen (aesthetics) und die (geometrische) Darstellung (geoms). Der Aufbau des Befehls ggplot() ist die Definition des Datensatzens (“my.data”) und der Variablen. Für eine univariate Datenvisualisierung ist dies die X-Variable. In der folgenden Grafik ist dies etwa tenure. Die Definition der Variablen erfolgt in dem Abschnitt zu aesthetics (aes). Danach spezifizieren wir die Art der Darstellung mit geom_histogram und legen weitere Aspekte fest (Beschriftung der Achsen mit labs, die Markierung der Y-Achse mit scale_y_continuous).
# Grafik für Vertragsdauer und monatliche Gebühren
g1<-ggplot(my.data, aes(x=tenure), na.rm=T)+geom_histogram(binwidth=3, fill="blue")+labs(x="Vertragsdauer",
y="Anzahl")+scale_y_continuous(breaks=seq(0, 1000, 100))
g1
g2<-ggplot(my.data, aes(x=MonthlyCharges))+geom_histogram(binwidth=5, fill="blue")+labs(x="Monatliche Gebühren (USD)",
y="Anzahl")+scale_y_continuous(breaks=seq(0, 1000, 100))
grid.arrange(g1, g2, ncol=2, nrow=1)
ggplot(my.data, aes(x=tenure, y=TotalCharges, colour=Churn))+geom_point()+scale_color_manual(values=c("green", "red"),
name="Kündigung")+theme(legend.position="bottom")+labs(x="Vertragsdauer", y="Gesamtgebühren")
## Warning: Removed 11 rows containing missing values (geom_point).
g2
Grafik 1: Häufigkeitsverteilung für Vertragsdauer und
monatliche Gebühren
Die monatlichen Ge-bühren und die Vertragsdauer ist bi-modal verteilt: es gibt viele Kunden mit einer sehr kurzen Vertragsdauer und niedrigen monatlich-en Gebühren (Grafik 1). Dem stehen relativ viele Kunden mit einer sehr hohen Vertragsdauer entgegen. Die Gebühren liegen ansonsten vor allem zwischen 70 und 90 USD.
In einem ersten Analyseschritt betrachten wir explorativ den bivariaten Zusammenhang zwischen Kündigungsverhalten und sozio-ökonomischen Faktoren sowie der Kundenbeziehung (Vertragsdauer, Vertragsumfang, Gebühren).
Grafik 2 vergleicht das Kündigungsverhalten zwischen verschiedenen sozio-ökonomischen Gruppen. Die Höhe des grünen Balkenanteils entsprich dem Prozentantail an Kunden in dieser Gruppe, die nicht gekündigt haben. Wir können sehen, dass Kunden mit Kindern und Partner seltener gekündigt haben als alleinstehende Kunden. Rentner kündigen häufiger als jüngere Kunden. Zwischen männlichen und weiblichen Kunden scheint es keinen Unterschied im Kündigungsverhalten zu geben.
Die Darstellung als Prozent erfolgt über percent_format(). Mit scale_fill_manual() geben wir die Farbe der Balken vor. Mit den Befehlen themes() und guides() spezifieren wir die allgemeine Darstellungsweise (hier: die Position der Legende) und Einzelheiten der Legende. Um eine gemeinsame Legende zu haben brauchen wir eine eigene Funktion.
# Funktion für gemeinsame legend
#http://www.sthda.com/english/wiki/ggplot2-easy-way-to-mix-multiple-graphs-on-the-same-page-r-software-and-datavisualization#grid.arrange-create-and-arrange-multiple-plots
get_legend<-function(myggplot){
tmp <- ggplot_gtable(ggplot_build(myggplot))
leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
legend <- tmp$grobs[[leg]]
return(legend)
}
# Interaktionseffekt Vertragsdauer und monatliche Gebühren?
## Bivariate Zusammenhänge mit der abhängigen Variable
# Sozioökonomische Variablen
f1<-ggplot(my.data, aes(x=gender, fill=Churn))+geom_bar(position="fill")+scale_y_continuous(labels =
percent_format())+scale_fill_manual(values=c("green", "red"), name="Kündigung")+guides(fill=guide_legend(reverse=T))+ylab("Anteil in
Prozent")+xlab("Geschlecht")+theme(legend.position="bottom")
f2<-ggplot(my.data, aes(x=Partner, fill=Churn))+geom_bar(position="fill")+scale_y_continuous(labels =
percent_format())+scale_fill_manual(values=c("green", "red"))+guides(fill=guide_legend(reverse=T))+ylab("Anteil in
Prozent")+xlab("Partner")+theme(legend.position="none")
f3<-ggplot(my.data, aes(x=Dependents, fill=Churn))+geom_bar(position="fill")+scale_y_continuous(labels =
percent_format())+scale_fill_manual(values=c("green", "red"))+guides(fill=guide_legend(reverse=T))+ylab("Anteil in
Prozent")+xlab("Kinder")+theme(legend.position="none")
f4<-ggplot(my.data, aes(x=SeniorCitizen, fill=Churn))+geom_bar(position="fill")+scale_y_continuous(labels =
percent_format())+scale_fill_manual(values=c("green", "red"))+guides(fill=guide_legend(reverse=T))+ylab("Anteil in
Prozent")+xlab("Renter")+theme(legend.position="none")
# Gemeinsame legend vorbereiten
legend <- get_legend(f1)
f1<-f1+theme(legend.position="none")
grid.arrange(f1, f2, f3, f4, legend, nrow=3, ncol=2, layout_matrix = rbind(c(1,2), c(3, 4), c(5,5)), widths = c(2.7, 2.7), heights = c(2.5, 2.5,
0.2))
Grafik 2: Kündigungen und sozio-ökonomische Gruppen
Das Kündigungsverhalten unterscheidet sich auch abhängig von der Länge der Vertragslaufzeit sowie der bisherigen Vertragsdauer und der Höhe der monatlichen Gebühren (Grafik 3). Verträge mit einer Vertragslaufzeit von einem Monat werden wesentlich häufiger gekündigt als Verträge mit einer ein- oder zweijährigen Laufzeit. Kunden, die schon länger einen Vertrag haben, kündigen proportional gesehen weniger als Neukunden. Ab einer Vertragsdauer von 20 Monaten bleiben mehr Kunden beim Unternehmen als kündigen. Kunden mit einer sehr geringen monatlichen Gebühr kündigen weniger häufig als Kunden mit höheren Gebühren.
# Dauer und Höhe der Gebühren
# prop.table(table(Churn, Contract))
h1<-ggplot(my.data, aes(x=Contract, fill=Churn))+geom_bar(position="fill")+scale_y_continuous(labels =percent_format())+scale_fill_manual(values=c("green", "red"), name="Kündigung")+guides(fill=guide_legend(reverse=T))+ylab("Anteil in Prozent")+xlab("Vertragslaufzeit")+theme(legend.position="bottom")
#ggplot(my.data, aes(x=Churn, y=tenure))+geom_boxplot()
h2<-ggplot(my.data, aes(x=tenure, fill=Churn))+geom_density(alpha=.3, color=NA)+scale_fill_manual(values=c("green", "red"), name="Kündigung")+labs(x="Vertragsdauer", y="Dichte")+theme(legend.position="none")
# ggplot(my.data, aes(x=Churn, y=MonthlyCharges))+geom_boxplot()+scale_fill_manual(values=c("green", "red"), name="Kündigung")
#ggplot(my.data, aes(x=MonthlyCharges, fill=Churn))+geom_density(alpha=.3, color=NA)+scale_fill_manual(values=c("green", "red"), name="Kündigung")
my.data$Monthly.cat<-cut(my.data$MonthlyCharges, seq(0,150,25))
h3<-ggplot(my.data, aes(x=Monthly.cat, fill=Churn))+geom_bar(position="fill")+scale_y_continuous(labels = percent_format())+scale_fill_manual(values=c("green", "red"))+guides(fill=guide_legend(reverse=T))+ylab("Anteil in Prozent")+xlab("Monatliche Gebühren (USD)")+theme(legend.position="none")+scale_x_discrete(labels=c("bis 25", "25-49", "50-74", "75-99","100-125"))
# ggplot(my.data, aes(x=Churn, y=TotalCharges))+geom_boxplot()
# ggplot(my.data, aes(x=TotalCharges, fill=Churn))+geom_density(alpha=.3, color=NA)
# Es gibt einen Zusammenhang zwischen Churn und tenure sowie MonthlyCharges
# Gemeinsame legend vorbereiten
legend <- get_legend(h1)
h1<-h1+theme(legend.position="none")
grid.arrange(h1, h2, h3, legend, nrow=2, ncol=3, layout_matrix = rbind(c(1,2, 3), c(4, 4,4)), widths = c(2.7, 2.7, 2.7), heights = c(2.5, 0.2))
Grafik 3: Kündigungen, Vertragsdauer und monatliche
Gebühren
Im Vergleich der der Rechnungsart (digital /Papier) und der Zahlart von Kunden zeigen sich auch Unterschiede im Kündigungsverhalten (Grafik 4). Kunden mit digitalen Rechnungen sowie Kunden, die elektronisch per Scheck zahlen, kündigen häufiger. Zwischen den anderen Zahlarten bestehen hingegen keine nennenswerten Unterschiede im Kündigungsverhalten.
Wir kombinieren hier mehrere Grafiken über grid.arrange().
i1<-ggplot(my.data, aes(x=PaperlessBilling, fill=Churn))+geom_bar(position="fill")+ylab("Anteil in Prozent")+scale_y_continuous(labels = percent_format())+scale_fill_manual(values=c("green", "red"), name="Kündigung")+xlab("Elektronische Rechnung")+scale_x_discrete(labels=c("Nein", "Ja"))+theme(legend.position="bottom")
i2<-ggplot(my.data, aes(x=PaymentMethod, fill=Churn))+geom_bar(position="fill")+scale_fill_manual(values=c("green", "red"), name="Kündigung")+ylab("Anteil in Prozent")+scale_y_continuous(labels = percent_format())+xlab("Zahlart")+scale_x_discrete(labels=c("Bankeinzug", "Kreditkarte", "Scheck (dig.)", "Scheck"))+theme(legend.position="none")
i1<-i1+theme(legend.position="none")
grid.arrange(i1, i2, legend, ncol=2, nrow=2, layout_matrix = rbind(c(1,2),c(3,3)), widths = c(2.7, 2.7), heights = c(2.5, 0.2))
Grafik 4: Kündigungen, Rechnungs- und Zahlart
Viele Kunden haben Zusatzdienstleistungen für ihre Internetverbindung abonniert. Grafik 5 vergleicht das Kündigungsverhalten zwischen Kunden mit und ohne die diversen Zusatzleistungen. Generell zeigt sich, dass Kunden mit Zusatzoptionen weniger häufig kündigen. Nur für die Streaming-Angebote gibt es keinen nennenswerten Unterschied im Kündigungsverhalten.
j1<-ggplot(my.data.internet, aes(x=OnlineSecurity, fill=Churn))+geom_bar(position="fill")+scale_y_continuous(labels =percent_format())+scale_fill_manual(values=c("green", "red"))+ylab("Anteil in Prozent")+xlab("Internetsicherheit")+scale_x_discrete(labels=c("Nein", "Ja"))+theme(legend.position="bottom")
j2<-ggplot(my.data.internet, aes(x=OnlineBackup, fill=Churn))+geom_bar(position="fill")+scale_y_continuous(labels = percent_format())+scale_fill_manual(values=c("green", "red"))+ylab("Anteil in Prozent")+xlab("Online Backup")+scale_x_discrete(labels=c("Nein", "Ja"))+theme(legend.position="none")
j3<-ggplot(my.data.internet, aes(x=DeviceProtection, fill=Churn))+geom_bar(position="fill")+scale_y_continuous(labels = percent_format())+scale_fill_manual(values=c("green", "red"))+ylab("Anteil in Prozent")+xlab("Geräteschutz")+scale_x_discrete(labels=c("Nein", "Ja"))+theme(legend.position="none")
j4<-ggplot(my.data.internet, aes(x=TechSupport, fill=Churn))+geom_bar(position="fill")+scale_y_continuous(labels = percent_format())+scale_fill_manual(values=c("green", "red"))+ylab("Anteil in Prozent")+xlab("Kundenbetreuung")+scale_x_discrete(labels=c("Nein", "Ja"))+theme(legend.position="none")
j5<-ggplot(my.data.internet, aes(x=StreamingTV, fill=Churn))+geom_bar(position="fill")+scale_y_continuous(labels = percent_format())+scale_fill_manual(values=c("green", "red"))+ylab("Anteil in Prozent")+xlab("Streaming (TV)")+scale_x_discrete(labels=c("Nein","Ja"))+theme(legend.position="none")
j6<-ggplot(my.data.internet, aes(x=StreamingMovies, fill=Churn))+geom_bar(position="fill")+scale_y_continuous(labels = percent_format())+scale_fill_manual(values=c("green", "red"))+ylab("Anteil in Prozent")+xlab("Streaming (Filme)")+scale_x_discrete(labels=c("Nein", "Ja"))+theme(legend.position="none")
j1<-j1+theme(legend.position="none")
grid.arrange(j1, j2, j3, j4, j5, j6, legend, ncol=3, nrow=3, layout_matrix = rbind(c(1,2,3),c(4,5,6), c(7,7,7)), widths = c(2.7, 2.7, 2.7), heights= c(2.5, 2.5, 0.2))
# Churn unterscheidet sich deutlich für Contract, SeniorCitizen, Partner,
# Dependents, Internetservice, OnlineSecurity, OnlineBackup, DeviceProtection,
# TechSupport, PaperlessBilling, PaymentMethod
Grafik 5: Kündigungen und Zusatzdienstleistungen für das Internet
Die explorative Datenanalyse zeigt teilweise deutliche Unterschiede im Kündigungsverhalten zwischen Kunden mit verschiedenen sozio-ökonomischen Status oder unterschiedlichen Vertrags-modalitäten. Insbesondere kündigen Neu-Kunden und Kunden mit monatlicher Vertragsdauer relativ häufig. Kunden mit Partnern oder Kindern kündigen seltener, Rentner hingegen kündigen vergleichsweise häufig. Kunden, die entweder sehr geringe monatliche Gebühren zahlen oder Zusatzleistungen gebucht haben, kündigen seltener.