Skip to content

EDA Parte 2

davidAlvarez24913 edited this page Aug 3, 2020 · 14 revisions

OutLiers

¿ Qué son outliers?

Los valores atípicos (outilers en inglés) son aquellos puntos que están mas allá del límite inferior o superior.

Definiciones Previas

"Primer cuartil: el 25% de los valores son menores o igual a este valor (punto 2 en el gráfico anterior). Mediana o Segundo Cuartil: Divide en dos partes iguales la distribución. De forma que el 50% de los valores son menores o igual a este valor (punto 3 en el gráfico siguiente). Tercer cuartil: el 75% de los valores son menores o igual a este valor (punto 4 en el gráfico siguiente). Rango Intercuartílico (RIC): Diferencia entre el valor del tercer cuartil y el primer cuartil."(Montes, 2020)

Proceso

  1. Para no abrazar errores, lo primero que debemos hacer y filtrar los datos nulos
  2. Calcular los cuartiles con stat.approxQuantile
  3. Calcular la desviación estándar y el promedio con: stddev y mean
  4. Calcular limite superior e inferior
  5. Calculo de IQR; es decir el rango intercuartil
  6. Presentar los datos considerados como valores admisibles
val data2= df.drop("id_persona").select($"ingreso_laboral").filter("ingreso_laboral is NOT  NULL")
data2.summary().show
val inilimit =0
val finlimit = 146030
val outliers = data2.stat.approxQuantile("ingreso_laboral",Array(0.25,0.75),0.00)
val dest= data2.select(stddev("ingreso_laboral")).first()(0).asInstanceOf[Double]
val avg= data2.select(mean("ingreso_laboral")).first()(0).asInstanceOf[Double]
val li = dest - 3 * avg
val ls = dest + 3 * avg

Podemos apreciar summary (resumen en español),nos brinda datos númericos significativos como los cuartiles, minimo, máximo, total de filas, promedio y desviación estándar del dataframe

summary ingreso_laboral
count 504742
mean 487.10984027483346
stddev 767.7250086176327
min 0
25% 170
50% 370
75% 588
max 146030

Luego filtramos en base al limite superior ls e invocamos summary

val newslimits = data2.filter(expr("ingreso_laboral") <= ls)
newslimits.toDF.summary().show
summary ingreso_laboral
count 497044
mean 435.3529385728426
stddev 378.2715590246983
min 0
25% 165
50% 360
75% 564
max 2229

De la misma manera calculamos los valores átipicos de la variable factor_expansión, y lo podemos encontrar en el notebook Outliers Fato de Expansión

Análisis Multivariado

Lo denominamos multivariado por trabajamos con variabas columnas como género, ingreso_laboral, nivel de instrucción ,entre otras.

Con el fin de poder tener datos especificos sin reescribir código creamos algunas funciones, como por ejemplo nivelInstruccion2, la que recibe dos parametros el nivel de instrucción y el año.

Funciónes

def nivelInstruccion2(nInstrc:String, anio:Int)={
    
    val aux = pro.select("nivel_de_instruccion","ingreso_laboral","anio","genero").filter($"nivel_de_instruccion"  === nInstrc && $"anio" ===anio).groupBy("nivel_de_instruccion","genero")
        .agg(count('nivel_de_instruccion).as("count"), avg('ingreso_laboral),  max('ingreso_laboral))
        
    val total = pro.filter($"nivel_de_instruccion" === nInstrc && $"anio" ===anio).count()
    
    val hom = aux.filter('genero === "1 - Hombre").drop('genero).select($"nivel_de_instruccion",$"avg(ingreso_laboral)",$"max(ingreso_laboral)",$"count".cast("Double")/total *100)
    val hom2 = hom.withColumnRenamed(hom.schema.last.name,"Hombres").withColumn("Hombres", format_number('Hombres, 2) ).withColumnRenamed("avg(ingreso_laboral)","SueldoPromedioHombres")
                .withColumn("SueldoPromedioHombres", format_number('SueldoPromedioHombres, 2) )
                .withColumnRenamed("max(ingreso_laboral)","SueldoMaxHombres")
    
    val muj = aux.filter('genero =!= "1 - Hombre").drop('genero).select($"nivel_de_instruccion",$"avg(ingreso_laboral)",$"max(ingreso_laboral)",$"count".cast("Double")/total *100)
    val muj2 = muj.withColumnRenamed(muj.schema.last.name,"Mujeres").withColumn("Mujeres", format_number('Mujeres, 2) ).withColumnRenamed("avg(ingreso_laboral)","SueldoPromedioMujeres")
                .withColumn("SueldoPromedioMujeres", format_number('SueldoPromedioMujeres, 2) )
                .withColumnRenamed("max(ingreso_laboral)","SueldoMaxMujeres")
    
    hom2.join( muj2 , "nivel_de_instruccion").select($"nivel_de_instruccion",$"Hombres" ,$"Mujeres" ,$"SueldoPromedioHombres" ,$"SueldoPromedioMujeres" ,$"SueldoMaxHombres" ,$"SueldoMaxMujeres").show     
}  

Resultado:

nivelInstruccion2("10 - Post-grado",2019)
nivel_de_instruccion Hombres Mujeres SueldoPromedioHombres SueldoPromedioMujeres SueldoMaxHombres SueldoMaxMujeres
10 - Post-grado 48.82 51.18 1,805.20 1,485.12 20000 25300

De manera similar realizamos nivelInstruccion3 y nivelInstruccion4, que se encuentran en el notebook Avances3Variable.zpln

nivelInstruccion3(2019)
nivel_de_instruccion Hombres Mujeres SueldoPromedioHombres SueldoPromedioMujeres SueldoMaxHombres SueldoMaxMujeres
09 - Superior Universitario 8.73 9.20 896.76 743.78 999 999
08 - Superior no universitario 1.23 0.99 794.83 580.16 998 990
05 - Educación Básica 2.79 1.47 278.24 217.42 97 990
10 - Post-grado 0.93 0.98 1,805.20 1,485.12 999 997
02 - Centro de alfabetización 0.18 0.28 193.78 146.69 91 97
01 - Ninguno 1.69 2.01 210.38 132.46 992 990
04 - Primaria 18.09 13.06 358.28 232.91 998 990
07 - Educación Media 7.35 4.34 353.64 287.94 995 988
06 - Secundaria 15.64 11.04 534.70 371.82 998 999
nivelInstruccion4("Loja","10 - Post-grado",2019)
provincia nivel_de_instruccion Hombres Mujeres SueldoPromedioHombres SueldoPromedioMujeres SueldoMaxHombres SueldoMaxMujeres
Loja 10 - Post-grado 46.34 53.66 1,645.11 1,190.36 800 996

CrossTab y Pivot

Ya que estamos tratando con mas de dos variables, y resulta un poco extensas las funciones, tenemos estas dos funciones .stat.crosstab y pivot, que nos permiten simplificar o disminuir la cantidad de código para responder una pregunta por ejemplo:

CorssTab

Nos permite trabajar con los datos únicos tanto de provincia y sectorizacion y presentar la frecuencia respecto de los mismos

z.show(data3.stat.crosstab("provincia", "sectorizacion").orderBy("provincia_sectorizacion"))

De la anterior consulta notamos el uso del .stat.crosstab, y además .show que nos permite hacer visualizaciones del dataframe que le pasemos como parametro.

Pivot

En la siguiente porción de código vemos el uso del pivot, y es muy diferente del crosstab ya que solo admite un argumento y funciona con los tipos de datos RelationalGroupedDataset, y pivot los genera por esto nos servimos de agg para agreagar las columnas que nesecitemos en nuestro caso el promedio del ingreso laboral y otras columnas mas, y al realizar esto creamos un dataframe

val avgSalGenero =data3.groupBy("rama_actividad").pivot("genero").agg(mean("ingreso_laboral"),max("ingreso_laboral"))
.orderBy($"rama_actividad")
val resultado = avgSalGenero.withColumnRenamed("1 - Hombre_avg(CAST(ingreso_laboral AS DOUBLE))","Hombres").withColumn("Hombres", format_number('Hombres,2))
.withColumnRenamed("2 - Mujer_avg(CAST(ingreso_laboral AS DOUBLE))","Mujeres").withColumn("Mujeres", format_number('Mujeres,2))
.withColumnRenamed("1 - Hombre_max(ingreso_laboral)","SueldoMaxHombre")
.withColumnRenamed("2 - Mujer_max(ingreso_laboral)","SueldoMaxMujer")
z.show(resultado)

Notebook CorssTabPivot

rama_actividad Hombres SueldoMaxHombre Mujeres SueldoMaxMujer
null 63.88 970 31.26 954
Agricultura, ganadería caza y silvicultura y pesca 301.46 999 177.15 998
Explotación de minas y canteras 924.98 998 801.59 997
Industrias manufactureras 544.63 999 361.10 999
Suministros de electricidad, gas, aire acondicionado 1,145.91 998 746.80 990
Distribución de agua, alcantarillado 699.80 998 727.03 995
Construcción 449.02 999 865.75 999
Comercio, reparación vehículos 584.75 999 366.05 999
Transporte y almacenamiento 502.47 998 543.60 997
Actividades de alojamiento y servicios de comida 539.17 999 354.65 998
Información y comunicación 805.92 998 500.95 996
Actividades financieras y de seguros 1,054.58 999 879.84 997
Actividades inmobiliarias 808.38 992 657.58 990
Actividades profesionales, científicas y técnicas 786.40 995 605.10 995
Actividades y servicios administrativos y de apoyo 561.86 998 353.06 995
Administración pública, defensa y seguridad social 1,092.45 999 1,011.21 999
Enseñanza 943.01 999 841.54 999
Actividades, servicios sociales y de salud 1,130.80 999 804.25 999
Artes, entretenimiento y recreación 540.08 998 511.05 990
Otras actividades de servicios 404.96 998 235.26 998