Para llevar a cabo este ejercicio práctico se va a utilizar un dataset público de Orange Telecom disponible en la página Kaggle. Este dataset contiene una muestra representativa de clientes de esta compañía y un conjunto de características que describen su actividad dentro de ella. El objetivo para el que fue creado este conjunto de datos es encontrar patrones que describan si un cliente va a darse de baja o no para intentar prevenir y reducir el churn. Para los que no estéis familiarizados con el churn, el churn se define como el porcentaje de clientes que dejan de utilizar los servicios que ofrece una empresa. Es un ejercicio de análisis muy repetido, no sólo en el sector de las Telecomunicaciones sino en otros muchos sectores.
El dataset está formado por las siguientes variables:
En cuanto a los ejercicios y su evaluación, el caso práctico está formado por 4 ejercicios cada uno relacionado con uno de los 4 temas vistos en esta asignatura.
En todos ellos se valorará no sólo el código sino también su explicación y la justificación de los resultados.
Se entregará una memoria que contenga tanto los códigos, como su salida y explicación. Esta memoria se puede hacer con la herramienta que se desee: Word, RMarkdown, etc. Se entregará en formato pdf o, en el caso que se desee utilizar RMarkdown, también se puede entregar como html. El nombre del archivo seguirá el siguiente patrón: apellidos_nombre_casopractico
Carga el fichero datos_telco.csv (cuidado con los tipos de datos) y calcula los estadísticos de centralidad y posición más importantes
data = read.csv('datos_telco.csv', sep=',', dec='.', header=TRUE)
data$Churn = as.logical(data$Churn)
summary(data)
## State Account.length Area.code International.plan
## Length:3333 Min. : 1.0 Min. :408.0 Length:3333
## Class :character 1st Qu.: 74.0 1st Qu.:408.0 Class :character
## Mode :character Median :101.0 Median :415.0 Mode :character
## Mean :101.1 Mean :437.2
## 3rd Qu.:127.0 3rd Qu.:510.0
## Max. :243.0 Max. :510.0
## Voice.mail.plan Number.vmail.messages Total.day.minutes Total.day.calls
## Length:3333 Min. : 0.000 Min. : 0.0 Min. : 0.0
## Class :character 1st Qu.: 0.000 1st Qu.:143.7 1st Qu.: 87.0
## Mode :character Median : 0.000 Median :179.4 Median :101.0
## Mean : 8.099 Mean :179.8 Mean :100.4
## 3rd Qu.:20.000 3rd Qu.:216.4 3rd Qu.:114.0
## Max. :51.000 Max. :350.8 Max. :165.0
## Total.day.charge Total.eve.minutes Total.eve.calls Total.eve.charge
## Min. : 0.00 Min. : 0.0 Min. : 0.0 Min. : 0.00
## 1st Qu.:24.43 1st Qu.:166.6 1st Qu.: 87.0 1st Qu.:14.16
## Median :30.50 Median :201.4 Median :100.0 Median :17.12
## Mean :30.56 Mean :201.0 Mean :100.1 Mean :17.08
## 3rd Qu.:36.79 3rd Qu.:235.3 3rd Qu.:114.0 3rd Qu.:20.00
## Max. :59.64 Max. :363.7 Max. :170.0 Max. :30.91
## Total.night.minutes Total.night.calls Total.night.charge Total.intl.minutes
## Min. : 23.2 Min. : 33.0 Min. : 1.040 Min. : 0.00
## 1st Qu.:167.0 1st Qu.: 87.0 1st Qu.: 7.520 1st Qu.: 8.50
## Median :201.2 Median :100.0 Median : 9.050 Median :10.30
## Mean :200.9 Mean :100.1 Mean : 9.039 Mean :10.24
## 3rd Qu.:235.3 3rd Qu.:113.0 3rd Qu.:10.590 3rd Qu.:12.10
## Max. :395.0 Max. :175.0 Max. :17.770 Max. :20.00
## Total.intl.calls Total.intl.charge Customer.service.calls Churn
## Min. : 0.000 Min. :0.000 Min. :0.000 Mode :logical
## 1st Qu.: 3.000 1st Qu.:2.300 1st Qu.:1.000 FALSE:2850
## Median : 4.000 Median :2.780 Median :1.000 TRUE :483
## Mean : 4.479 Mean :2.765 Mean :1.563
## 3rd Qu.: 6.000 3rd Qu.:3.270 3rd Qu.:2.000
## Max. :20.000 Max. :5.400 Max. :9.000
PISTA: Existe una función en R que calcula todos a la vez
¿Qué variable cuantitativa tiene mayor coeficiente de asimetría? ¿Qué significa? Represéntala con un histograma
#La variable Total.intl.calls es la que tiene el mayor coeficiente de asimetria, esto significa que la variable es una asimetria pisitiva ya que hay más valores alejados de la media a la derecha.
skewness(data$Total.intl.calls)
## [1] 1.320883
#Histograma.
hist(data$Total.intl.calls)
¿Qué variable cuantitativa tiene mayor curtosis? ¿Qué significa?
#La variable que tieme mayor curtosis es Total.intl.calls, esto significa que su forma es mas escarpada.
kurtosis(data$Total.intl.calls)
## [1] 6.077165
Calcula la matriz de correlaciones (de las variables cuantitativas). ¿Existe algún par de variables con alta correlación?
#Si existen variable con corelaciones positivas y negativas como se demuestra en el grafico
data_num = data %>% select(Account.length,Area.code,Number.vmail.messages,Total.day.minutes,Total.day.calls, Total.day.charge,Total.eve.minutes,Total.eve.calls,Total.eve.charge,Total.night.minutes,Total.night.calls, Total.night.charge,Total.intl.minutes,Total.intl.calls,Total.intl.charge,Customer.service.calls)
matriz_cor = cor(data_num)
matriz_cor
## Account.length Area.code Number.vmail.messages
## Account.length 1.000000000 -0.012463497 -0.0046278243
## Area.code -0.012463497 1.000000000 -0.0019943701
## Number.vmail.messages -0.004627824 -0.001994370 1.0000000000
## Total.day.minutes 0.006216021 -0.008264366 0.0007782741
## Total.day.calls 0.038469882 -0.009646044 -0.0095480677
## Total.day.charge 0.006214135 -0.008264441 0.0007755235
## Total.eve.minutes -0.006757142 0.003580395 0.0175620343
## Total.eve.calls 0.019259967 -0.011886271 -0.0058643513
## Total.eve.charge -0.006745302 0.003606690 0.0175777801
## Total.night.minutes -0.008955192 -0.005824660 0.0076811359
## Total.night.calls -0.013176275 0.016522317 0.0071230629
## Total.night.charge -0.008959535 -0.005845376 0.0076632904
## Total.intl.minutes 0.009513902 -0.018288168 0.0028561959
## Total.intl.calls 0.020661428 -0.024178589 0.0139573387
## Total.intl.charge 0.009545675 -0.018394696 0.0028836579
## Customer.service.calls -0.003795939 0.027572226 -0.0132625831
## Total.day.minutes Total.day.calls Total.day.charge
## Account.length 0.0062160205 0.038469882 0.0062141347
## Area.code -0.0082643662 -0.009646044 -0.0082644411
## Number.vmail.messages 0.0007782741 -0.009548068 0.0007755235
## Total.day.minutes 1.0000000000 0.006750414 0.9999999522
## Total.day.calls 0.0067504139 1.000000000 0.0067529620
## Total.day.charge 0.9999999522 0.006752962 1.0000000000
## Total.eve.minutes 0.0070425110 -0.021451408 0.0070496072
## Total.eve.calls 0.0157689932 0.006462114 0.0157692822
## Total.eve.charge 0.0070290353 -0.021449263 0.0070361315
## Total.night.minutes 0.0043233666 0.022937845 0.0043238794
## Total.night.calls 0.0229724555 -0.019556965 0.0229724195
## Total.night.charge 0.0043003570 0.022926638 0.0043008608
## Total.intl.minutes -0.0101545856 0.021564794 -0.0101568616
## Total.intl.calls 0.0080333570 0.004574268 0.0080315720
## Total.intl.charge -0.0100919742 0.021666095 -0.0100942572
## Customer.service.calls -0.0134231864 -0.018941930 -0.0134269694
## Total.eve.minutes Total.eve.calls Total.eve.charge
## Account.length -0.006757142 0.019259967 -0.006745302
## Area.code 0.003580395 -0.011886271 0.003606690
## Number.vmail.messages 0.017562034 -0.005864351 0.017577780
## Total.day.minutes 0.007042511 0.015768993 0.007029035
## Total.day.calls -0.021451408 0.006462114 -0.021449263
## Total.day.charge 0.007049607 0.015769282 0.007036131
## Total.eve.minutes 1.000000000 -0.011430108 0.999999776
## Total.eve.calls -0.011430108 1.000000000 -0.011422894
## Total.eve.charge 0.999999776 -0.011422894 1.000000000
## Total.night.minutes -0.012583678 -0.002092768 -0.012592020
## Total.night.calls 0.007585643 0.007709706 0.007595843
## Total.night.charge -0.012592806 -0.002055984 -0.012601142
## Total.intl.minutes -0.011034714 0.008702881 -0.011042582
## Total.intl.calls 0.002541292 0.017433692 0.002541458
## Total.intl.charge -0.011066621 0.008673858 -0.011074499
## Customer.service.calls -0.012984553 0.002422575 -0.012987407
## Total.night.minutes Total.night.calls Total.night.charge
## Account.length -0.008955192 -0.0131762751 -0.008959535
## Area.code -0.005824660 0.0165223169 -0.005845376
## Number.vmail.messages 0.007681136 0.0071230629 0.007663290
## Total.day.minutes 0.004323367 0.0229724555 0.004300357
## Total.day.calls 0.022937845 -0.0195569654 0.022926638
## Total.day.charge 0.004323879 0.0229724195 0.004300861
## Total.eve.minutes -0.012583678 0.0075856431 -0.012592806
## Total.eve.calls -0.002092768 0.0077097055 -0.002055984
## Total.eve.charge -0.012592020 0.0075958430 -0.012601142
## Total.night.minutes 1.000000000 0.0112038563 0.999999215
## Total.night.calls 0.011203856 1.0000000000 0.011187820
## Total.night.charge 0.999999215 0.0111878197 1.000000000
## Total.intl.minutes -0.015207297 -0.0136049964 -0.015213526
## Total.intl.calls -0.012353432 0.0003045795 -0.012329215
## Total.intl.charge -0.015179849 -0.0136301696 -0.015186139
## Customer.service.calls -0.009287613 -0.0128019273 -0.009276954
## Total.intl.minutes Total.intl.calls Total.intl.charge
## Account.length 0.009513902 0.0206614284 0.009545675
## Area.code -0.018288168 -0.0241785887 -0.018394696
## Number.vmail.messages 0.002856196 0.0139573387 0.002883658
## Total.day.minutes -0.010154586 0.0080333570 -0.010091974
## Total.day.calls 0.021564794 0.0045742682 0.021666095
## Total.day.charge -0.010156862 0.0080315720 -0.010094257
## Total.eve.minutes -0.011034714 0.0025412917 -0.011066621
## Total.eve.calls 0.008702881 0.0174336921 0.008673858
## Total.eve.charge -0.011042582 0.0025414580 -0.011074499
## Total.night.minutes -0.015207297 -0.0123534324 -0.015179849
## Total.night.calls -0.013604996 0.0003045795 -0.013630170
## Total.night.charge -0.015213526 -0.0123292150 -0.015186139
## Total.intl.minutes 1.000000000 0.0323038841 0.999992742
## Total.intl.calls 0.032303884 1.0000000000 0.032372145
## Total.intl.charge 0.999992742 0.0323721453 1.000000000
## Customer.service.calls -0.009639680 -0.0175605992 -0.009674732
## Customer.service.calls
## Account.length -0.003795939
## Area.code 0.027572226
## Number.vmail.messages -0.013262583
## Total.day.minutes -0.013423186
## Total.day.calls -0.018941930
## Total.day.charge -0.013426969
## Total.eve.minutes -0.012984553
## Total.eve.calls 0.002422575
## Total.eve.charge -0.012987407
## Total.night.minutes -0.009287613
## Total.night.calls -0.012801927
## Total.night.charge -0.009276954
## Total.intl.minutes -0.009639680
## Total.intl.calls -0.017560599
## Total.intl.charge -0.009674732
## Customer.service.calls 1.000000000
corrplot(matriz_cor, type="upper")
Observación: No tendría sentido calcular la correlación de variables cualitativas pues la correlación mide la dependencia lineal entre dos variables, es decir, si cuando una crece la otra crece o si cuando una crece la otra decrece. No tiene sentido decir que una variable cualitativa crece o decrece.
¿Existe relación entre tener o no plan internacional y darse de baja? ¿Y en tener o no voic.mail.plan? Estudia si los que tienen contratados estos servicios se dan más o menos de baja que los que no lo tienen. Explícalo tanto numérica como gráficamente
#International plan
conteo = data %>% count(International.plan, Churn)
ggplot(conteo, aes(International.plan, n, fill=Churn)) +
geom_bar(stat="identity") +
labs(title="Diagrama de barras",
x= "International Plan",
y="Cliente de baja") +
scale_fill_brewer(palette = "Accent")
#Voice mail plan
conteo = data %>% count(Voice.mail.plan, Churn)
ggplot(conteo, aes(Voice.mail.plan, n, fill=Churn)) +
geom_bar(stat="identity") +
labs(title="Diagrama de barras",
x= "Voice Mail Plan",
y="Cliente de baja") +
scale_fill_brewer(palette = "Accent")
¿Existe alguna relación entre las llamadas al servicio de atención al cliente y la tasa de bajas? Explícalo tanto numérica como gráficamente
ggplot(data=data, aes(Customer.service.calls))+
geom_histogram(binwidth=10,color="dark blue",fill="blue")+ #modificamos anchura de las barras y el color
labs(x="Customer service calls", y="Counts")+ #Damos nombre a los ejes
ggtitle("Llamadas al servicio al cliente por la tasa de bajas")+ #Añadimos un titulo al grafico
facet_grid(Churn~.) #Grid por clase
Uno de los resultados más importantes que hemos visto en el tema sobre Teoría de la Probabilidad ha sido el Teorema Central del Límite. Este teorema es fundamental para la Estadística Inferencial y, por ello, es fundamental que comprendáis a la perfección en qué consiste.
El objetivo de este ejercicio es realizar una simulación que demuestre el Teorema Central del Límite. Para ello, se propone seguir los siguientes pasos y completar el código:
PASO 1: Generar 1000 muestras no normales de tamaño \(n=30\) y calcular sus correspondientes medias muestrales. Se propone generar muestras que sigan una distribución beta con parámetros \(\small \alpha=2\) y \(\small \beta=6\)
# Parametros enunciado
n = 30
alpha = 2
beta = 6
#Creamos 1000 muestras que siguen una distribucion beta y vamos guardando su media muestral en el vector medias_muestrales
medias_muestrales <- c()
for (i in 1:1000) {
muestra = rbeta(n, alpha, beta) #TODO: generar muestra distribucion beta tamano n y parametroa alpha y beta
media_muestral = mean(muestra)#TODO: calcula la media de la muestra
medias_muestrales = c(medias_muestrales, media_muestral)
}
PISTA: Si ejecutáis ?Distributions R os mostrará todas las distribuciones que tiene disponibles y podréis encontrar con qué función generar la muestra con distribución beta.
PASO 2: Calcular su media poblacional \(\small \mu\) y desviación típica poblacional \(\small \sigma\). En una distribución beta la media y desviación típica poblacional se calcula con las siguientes ecuaciones:
\[\small \mu = \frac{\alpha}{\alpha+\beta}\] \[\small \sigma = \sqrt{\frac{\alpha·\beta}{(\alpha+\beta)^2·(\alpha+\beta+1)}}\]
media_poblacional = alpha / (alpha + beta)#TODO: Calcula mu
sd_poblacional = sqrt(alpha * beta / ((alpha + beta)^2 * (alpha + beta + 1))) #TODO: Calcula sigma
cat('La media poblacional es igual a ', media_poblacional, 'y la desviación típica poblacional es igual a ', sd_poblacional)
PASO 3: Comprobar gráficamente que la distribución de las medias muestrales, es decir que la variable media_muestrales, sigue una normal de media \(\mu\) y desviación típica \(\frac{\sigma}{\sqrt(n)}\). Utiliza un histograma y/o las funciones qqnorm y qqline para demostrarlo
#TODO hacer histograma
# Histograma
hist(medias_muestrales, breaks = 30, freq = FALSE, main = "Distribución de medias muestrales",
xlab = "Media muestral", ylab = "Densidad")
curve(dnorm(x, mean = media_poblacional, sd = sd_poblacional / sqrt(n)), col = "red", add = TRUE)
# Gráfico QQ
qqnorm(medias_muestrales, main = "Gráfico QQ", xlab = "Cuantiles teóricos",
ylab = "Cuantiles de la muestra")
qqline(medias_muestrales, col = "red")
PASO 4: Calcular la media y desviación de la variable medias_muestrales
media = mean(medias_muestrales) #TODO: Calcular media de medias_muestrales
std = sd(medias_muestrales) #TODO: Calcular desviacion medias_muestrales
cat('La media de esta distribución normal es ', media)
cat('La desviación típica es igual a ', std)
PASO 5 ¿Se cumple que la distribución de las medias_muestrales es una \(\small N(\mu, \frac{\sigma}{\sqrt{n}})\)?
#TODO: Comprobar que la media de medias muestrales coincide con la media poblacional
#TODO: Comprobar que la desviacion de las medias muestrales coincide con la desviacion poblacional entre raiz de n
# Comprobar si se cumple que la distribución de las medias muestrales sigue una distribución normal
comprobacion_1 = abs(media - media_poblacional) < 0.05 # Usamos un nivel de significación del 5%
comprobacion_2 = abs(std - sd_poblacional/sqrt(n)) < 0.05 # Usamos un nivel de significación del 5%
# Resultados
if (comprobacion_1 & comprobacion_2) {
cat("Se cumple que la distribución de las medias muestrales sigue una distribución normal de media", media_poblacional, "y desviación estándar", sd_poblacional/sqrt(n))
} else {
cat("No se cumple que la distribución de las medias muestrales sigue una distribución normal de media", media_poblacional, "y desviación estándar", sd_poblacional/sqrt(n))
}
Calcula el intervalo de confianza para la media de la variable Total.day.minutes a nivel \(\small \alpha=0.05\). Es muy importante justificar la elección del intervalo, comprobar las hipótesis y/o mencionar los teoremas que utilizas si fuese necesario.
n = length(data$Total.day.minutes)
media = mean(data$Total.day.minutes)
std_error = sd(data$Total.day.minutes) / sqrt(n)
alpha = 0.05
z_value = qnorm(1 - (alpha / 2))
lower_limit = media - (z_value * std_error)
upper_limit = media + (z_value * std_error)
cat("El intervalo de confianza al 95% para la media de Total.day.minutes es (", round(lower_limit, 2), ", ", round(upper_limit, 2), ")")
## El intervalo de confianza al 95% para la media de Total.day.minutes es ( 177.93 , 181.62 )
En la prensa ha salido el titular “La empresa Orange Telecom tiene un 13% de bajas este mes”. Ya que nosotros tenemos una muestra representativa de más de 3K clientes podemos testear si esta afirmación es cierta o no. ¿Podemos decir a nivel \(\small \alpha=0.01\) que la tasa de bajas ha sido mayor? ¿Y a nivel \(\small \alpha=0.001\)?
n = length(data$Total.day.minutes)
media = mean(data$Total.day.minutes)
std_error = sd(data$Total.day.minutes) / sqrt(n)
alpha = 0.05
z_value = qnorm(1 - (alpha / 2))
lower_limit = media - (z_value * std_error)
upper_limit = media + (z_value * std_error)
cat("El intervalo de confianza al 95% para la media de Total.day.minutes es (", round(lower_limit, 2), ", ", round(upper_limit, 2), ")")
## El intervalo de confianza al 95% para la media de Total.day.minutes es ( 177.93 , 181.62 )
alpha = 0.001
p = 0.13
clientes = 3000
tasa_de_baja = rbinom(n=clientes, size=1, prob = 0.13)
bajas = as.data.frame(tasa_de_baja)
bajas %>% head()
## tasa_de_baja
## 1 0
## 2 0
## 3 0
## 4 0
## 5 0
## 6 1
conteos <- bajas %>% count(tasa_de_baja)
conteos
## tasa_de_baja n
## 1 0 2573
## 2 1 427
p_estim = nrow(bajas %>% filter(tasa_de_baja==1))/clientes
cat('la tasa de bajas ha sido de ', p_estim*100, '%')
## la tasa de bajas ha sido de 14.23333 %
z = (p_estim - p)/sqrt((p*(1-p))/clientes)
cat('El estadístico de contraste z es igual a ', z)
## El estadístico de contraste z es igual a 2.008676
pvalue = pnorm(-z, lower.tail = TRUE) + pnorm(z, lower.tail = FALSE) #Si lower.tail = FALSE calcula P(Z>z) si es TRUE P(Z<z)
cat('p-valor =', pvalue)
## p-valor = 0.04457155
cat('¿ p-valor < ', alpha, '? ', pvalue<alpha)
## ¿ p-valor < 0.001 ? FALSE