<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Introducción a la programación estadística <br/> con Python y Pandas (...)
Herramientas que usaremos
Python
Pandas
    Libreria que provee simples pero poderosas estructuras y herramientas para el analisis de datos
Jupyter Notebook
    Ambiente web para la creacion de documentos interactivos con elementos de programacion y datos (Python es solo uno de los multiples lenguajes que soporta)
NumPy
    Libreria base que provee estructuras de datos optimizadas (fast! fast! fast!) para el analisis (arreglo multidimensional
Step1:  Cargamos el archivo a un DataFrame en memoria
El archivo es separado por ';'.
Asi como read_csv, existen funciones para leer
Step2:  Demos un vistazo a los primeros 5 registros
Step3:  y a los ultimos 10
Step4:  Que tamaño tiene nuestro DataFrame?
Step5:  En español?
5,416 registros y 5 columnas
Nuestro DataFrame parece una tabla o una hoja de cálculo...
Cada registro tiene un indice (hasta ahora numerico y autoasignado), cada columna tiene nombre y un tipo de datos...
...parecen no necesitar mucha explicación. Aún así veamos que nos dice Pandas
Step6:  Limpieza de data
Valores faltantes o nulos
El conteo de cada columna y el tipo nos sugiere que no hay valores faltantes. Pero, vamos a confirmarlo
Step7:  Normalizar o limpiar los nombres de las columnas
El DataFrame tiene una propiedad columns que es (como) una lista de los nombres de las columnas.
Step8:  La columna Salario parece tener un espacio de mas. Esto nos importa porque por comodidad queremos acceder a los valores de cada columna haciendo algo como
Step9:  Arreglemos eso de una forma que se asegure que todos los nombres de columnas esten "limpios". Para eso
Step10:  Ahora todas las columnas tienen nombres sencillos, faciles de utilizar.
Salarios limpios
Step11:  La columna salario tiene un tipo de dato object. Esto normalmente se refiere a texto libre. Para nuestro analisis necesitamos interpretar los valores como números.
Con la función apply le aplicamos una operación a cada valor de la columna. En este caso usamos un lambda (o funcion anonima) para
Step12:  Veamos como quedo
Step13:  Resumen de 7 números
Habiendo realizado la conversión podemos ver estadísticas descriptivas básicas (por fin!) de los salarios.
Step14:  Limpie su puesto
Step15:  271 puestos diferentes? Vamos a asegurarnos que no se abulte esta cantidad debido a que un mismo puesto este escrito con espacios de más como paso con la columna Salario (o sin acentos).
Para esto necesitaremos uno que otro truco cuya explicación escapa al alcance de la presentación (pero que puede ser replicada con un poco de stackoverflow)
Brevemente
Step16:  Oh sorpresa! Ahora son 269 puestos en lugar de 271.
Se deja de ejercicio al interesado averiguar cuales valores fueron eliminados
Todos los generos son limpios
Step17:  Y los meses tambien
Step18:  Empezar a explorar un poco
Filtrar y seleccionar data
Separemos la nomina de cada mes disponible.
Step19:  High-rollers
Veamos las posiciones de grandes salarios. Filtramos con una condicion y seleccionamos las columnas que nos interesan
Step20:  Si se seleccionamos las columnas y despues filtramos, tambien funciona?
Step21:  Por que?
Step22:  Resulta que la condicion devuelve una serie de booleanos indicando cuales registros cumplen con la condicion.
Agrupar data (Group By)
Agrupar o separar los datos según los valores de una columna es el primer paso, conocido como split, de patrón split-apply-combine que veremos de manera natural aquí.
Step23:  groupby nos da un colección que relaciona el nombre de cada grupo con la parte de la data que pertenece a dicho grupo.
Step24:  Pero tambien nos permite hacerle preguntas a los distintos grupos a la vez. En efecto llevando a cabo los pasos
Step25:  Podemos agrupar por cualquier numero de columnas que querramos, formando una jerarquia de profundidad arbitraria.
Step26:  Proporción de la empleomanía por genero
Podemos realizar varios pasos tipo apply en hilo, inclusive con operaciones arbitrarias (funciones anonimas o lambdas)
Step27:  Proporción de la nomina por genero
Step28:  Se fijaron bien?
Las mujeres son el 58.97% de la empleomanía y el 60.41% de la nómina. Mientras que los hombres son el 41.02% de la empleomanía y el 39.59% de la nómina.
Hmmm...
A graficar un poco
Resulta que con Pandas, podemos continuar el hilo de apply y convertir la tabla en un grafico de barra muy facilmente. En este caso, la proporción de la nómina asignada a hombres y mujeres.
Step29:  Mejoremos el look un poco con Seaborn
La libreria de visualización Seaborn es
Step30:  Proporción de la nómina asignada a mujeres y hombres (reloaded)
Aquí vemos como el estilo del gráfico cambio solo por importar Seaborn. A mi me parece más bonito.
Step31:  Histogramas del Salario
Step32:  Histograma por genero (lado a lado)
Step33:  Diagrama de cajas (box & whiskers)
Step34:  Una tangente (a)normal
Cómo se vería una distribución normal (gaussiana) si tuviera la media y desviación que vemos empíricamente en los datos?
Seaborn y Numpy al rescate!
Step35:  Empecemos a enfocar nuestra exploración
Diference entre salario promedio por genero
Step36:  Parece ser que el salario promedio de las mujeres supero en 2601.05 DOP al de los hombres...
Relacion salario mujeres y hombres
Step37:  Sin controlar por ningun otro factor
Step38:  En el primer cuartil de salarios la mujer promedio gano 4.30% (783.97 DOP) menos que el hombre promedio.
Step39:  Que pasa cuando miramos los grupos que mas ganan?
Step40:  En el ultimo cuartil la mujer promedio gano 9% (7294.20 DOP) menos que el hombre promedio. Pero, notan algo extraño?
Step41:  Cual es el impacto de la persona que mas gana en la diferencia?
Outliers o valores extremos
Step42:  Ahora la diferencia se redujo a 7.10% (5,632.26 DOP) menos en salario promedio para las mujeres que los hombres.
En este caso, a manera ilustrativa, consideramos que el salario más alto dista demasiado de los demás y su influencia distorsiona lo que queremos evaluar.
Step43:  Profundicemos de cuartiles a deciles
Veamos el comportamiento del salario promedio por genero para cada decil. Para eso necesitaremos
Step44:  Graficamente es mas bonito
Seaborn es esteticamente más agradable y suele ahorrar mucho trabajo, los gráficos de Pandas se consiguen de la manera más facil; pero a veces es necesario modificar detalles que requieren usar matplotlib directamente.
Step45:  Soy yo a las líneas están superpuestas en todos los deciles excepto el primero y el último?
Mismo trabajo = mismo sueldo?
Hasta ahora hemos estado mirando la nómina total, por género y por decil pero sin importar la posición.
Realmente es justo comparar los salarios entre diferentes puestos?
Miremos solamente los puestos que tienen 20+ empleados y por lo menos un hombre y una mujer (otro split-apply-combine)
Step46:  Cuales puestos quedaron?
Y cuantos empleados hay en cada uno?
Step47:  Cómo se ve el salario en general por género de esta subpoblación?
Step48:  Y el salario para cada puesto por género?
Veamos los puestos ordenado de menor a mayor por el salario promedio de las mujeres que los ocupan.
Step49:  Calculemos la diferencia entre los promedios de cada puesto
Restandole al salario promedio de las mujeres el promedio de los hombres.
Step50:  En terminos relativos (%)?
<ASSISTANT_TASK:>
Python Code:
import pandas as pd
Explanation: Introducción a la programación estadística <br/> con Python y Pandas (...)
Herramientas que usaremos
Python
Pandas
    Libreria que provee simples pero poderosas estructuras y herramientas para el analisis de datos
Jupyter Notebook
    Ambiente web para la creacion de documentos interactivos con elementos de programacion y datos (Python es solo uno de los multiples lenguajes que soporta)
NumPy
    Libreria base que provee estructuras de datos optimizadas (fast! fast! fast!) para el analisis (arreglo multidimensional: Ndarray)
matplotlib
    Libreria base de visualización
Seaborn
    Libreria para visualizacion estadistica, construida sobre matplotlib para ser mucho mas facil de usar y amigable
todo lo anterior se consigue con solo instalar Anaconda (la distribución de Python más popular)
dos o tres cositas mas...
Cosas que no veremos
la historia de Python
ni las razones para usarlo
tampoco veremos el millon de cosas que se pueden hacer con Python y su ecosistema
detalles tecnicos como instalacion/configuracion, 
conceptos de programacion/implementación "avanzados" (les pasaremos por arribita si es necesario)
Que si veremos?
Pues cómo:
importar datos de un archivo (csv)
ver la estructura básica de los datos
realizar un minímo de limpieza y orden:
Transformar campos
Agregar nuevos campos
acceder al contenido de:
columnas especificas
registros especificos
calcular estadisticas descriptivas
Rango, media, desviación estandar
Cuantiles
resumen de 7 números
explorar subdivisiones de los datos
group by
split-apply-combine
generar algunos graficos
Histograma
Diagrama de caja
...y uno que otro extra, si da tiempo...
Pero con cuáles datos?
Un archivo de la Nómina Mensual de la DGII en Febrero y Enero 2016 que yo tome del repositorio de datos abiertos del gobierno de Republica Dominicana (http://datos.gob.do/dataset/nomina-de-empleados-dgii-2016) hace ya más de un año....
Y que al parecer ya no está disponible en el portal datos.gob.do ni en la página de la DGII
Importemos la libreria pandas con el alias pd (por convencion)
End of explanation
# DataFrame cariñosamente df
df = pd.read_csv('cs_DGII_Nomina_2016.csv',sep=';', encoding="ISO-8859-1") # encoding???
Explanation: Cargamos el archivo a un DataFrame en memoria
El archivo es separado por ';'.
Asi como read_csv, existen funciones para leer:
* excel
* SAS
* STATA
* archivos de longitud fija
* JSON, entre otros...
End of explanation
df.head()
Explanation: Demos un vistazo a los primeros 5 registros
End of explanation
df.tail(10)
Explanation: y a los ultimos 10
End of explanation
df.shape
Explanation: Que tamaño tiene nuestro DataFrame?
End of explanation
df.info()
Explanation: En español?
5,416 registros y 5 columnas
Nuestro DataFrame parece una tabla o una hoja de cálculo...
Cada registro tiene un indice (hasta ahora numerico y autoasignado), cada columna tiene nombre y un tipo de datos...
...parecen no necesitar mucha explicación. Aún así veamos que nos dice Pandas:
End of explanation
df.isnull().any()
Explanation: Limpieza de data
Valores faltantes o nulos
El conteo de cada columna y el tipo nos sugiere que no hay valores faltantes. Pero, vamos a confirmarlo:
End of explanation
df.columns
Explanation: Normalizar o limpiar los nombres de las columnas
El DataFrame tiene una propiedad columns que es (como) una lista de los nombres de las columnas.
End of explanation
df.Mes.head()
Explanation: La columna Salario parece tener un espacio de mas. Esto nos importa porque por comodidad queremos acceder a los valores de cada columna haciendo algo como:
End of explanation
df.columns = [x.strip().lower() for x in df.columns.values]
df.columns
Explanation: Arreglemos eso de una forma que se asegure que todos los nombres de columnas esten "limpios". Para eso:
iteramos por cada columna e invocamos funciones propias del tipo de dato string para limpiarlos (gracias Python)
usamos strip para quitar espacios delante y detras
y finalmente lower para convertir todo a minusculas
End of explanation
df.salario.head()
Explanation: Ahora todas las columnas tienen nombres sencillos, faciles de utilizar.
Salarios limpios
End of explanation
limpiar_salario = lambda x: pd.to_numeric(x.replace(',','').strip(), errors='coerce')
df.salario = df.salario.apply(limpiar_salario)
Explanation: La columna salario tiene un tipo de dato object. Esto normalmente se refiere a texto libre. Para nuestro analisis necesitamos interpretar los valores como números.
Con la función apply le aplicamos una operación a cada valor de la columna. En este caso usamos un lambda (o funcion anonima) para:
* quitar las comas y los espacios en blanco (replace y strip)
* convertir a número (to_numeric)
End of explanation
df.salario.head()
Explanation: Veamos como quedo:
End of explanation
df.salario.describe()
Explanation: Resumen de 7 números
Habiendo realizado la conversión podemos ver estadísticas descriptivas básicas (por fin!) de los salarios.
End of explanation
df.puesto.describe()
Explanation: Limpie su puesto
End of explanation
from unidecode import unidecode
import re
def limpiar_puesto(pstr):
    pstr = unidecode(pstr).strip().lower()
    pstr = re.sub('\(.*?\)','', pstr)
    pstr = pstr.translate({ord('.'): None, ord(','): None})
    return pstr
# tambien podemos acceder a las columnas con esta notación df['columna']
df['puesto_clean'] = df.puesto.apply(limpiar_puesto)
df.puesto_clean.describe()
Explanation: 271 puestos diferentes? Vamos a asegurarnos que no se abulte esta cantidad debido a que un mismo puesto este escrito con espacios de más como paso con la columna Salario (o sin acentos).
Para esto necesitaremos uno que otro truco cuya explicación escapa al alcance de la presentación (pero que puede ser replicada con un poco de stackoverflow)
Brevemente:
* definimos una funcion limpiar_puesto donde
    * usamos unidecode para que nos ayude a quitar los acentos
    * usamos re para con una expresión regular quitar los fragmentos entre parentesis de los puestos
    * usamos translate para quitar puntos y comas no deseados
* le aplicamos esta funcion a los datos de la columna puesto para crear una nueva columna puesto_clean
End of explanation
df.genero.value_counts()
df.genero.describe()
Explanation: Oh sorpresa! Ahora son 269 puestos en lugar de 271.
Se deja de ejercicio al interesado averiguar cuales valores fueron eliminados
Todos los generos son limpios
End of explanation
df.mes.value_counts()
df.mes.describe()
df.to_csv('dgii_clean.csv')
Explanation: Y los meses tambien
End of explanation
ene = df[df.mes == 'ene-16']
feb = df[df.mes == 'feb-16']
print(ene.shape)
print(feb.shape)
Explanation: Empezar a explorar un poco
Filtrar y seleccionar data
Separemos la nomina de cada mes disponible.
End of explanation
ene[ene.salario > 250000][['puesto_clean','salario','genero']]
Explanation: High-rollers
Veamos las posiciones de grandes salarios. Filtramos con una condicion y seleccionamos las columnas que nos interesan:
End of explanation
ene[['puesto_clean','salario','genero']][ene.salario > 250000]
Explanation: Si se seleccionamos las columnas y despues filtramos, tambien funciona?
End of explanation
(ene.salario > 250000).head()
Explanation: Por que?
End of explanation
por_mes = df.groupby(by='mes')
por_mes
Explanation: Resulta que la condicion devuelve una serie de booleanos indicando cuales registros cumplen con la condicion.
Agrupar data (Group By)
Agrupar o separar los datos según los valores de una columna es el primer paso, conocido como split, de patrón split-apply-combine que veremos de manera natural aquí.
End of explanation
for mes, data_mes in por_mes:
    print(mes, data_mes.shape)
Explanation: groupby nos da un colección que relaciona el nombre de cada grupo con la parte de la data que pertenece a dicho grupo.
End of explanation
por_mes.salario.describe()
Explanation: Pero tambien nos permite hacerle preguntas a los distintos grupos a la vez. En efecto llevando a cabo los pasos:
split : separar los datos por el mes al que pertenecen
apply : a cada grupo formado aplicarle la operación describe
combine : tomar los resultados y combinarlos en una nueva tabla resultado
Todo esto, en un simple línea de código:
End of explanation
df.groupby(by=['mes','genero']).salario.describe()
Explanation: Podemos agrupar por cualquier numero de columnas que querramos, formando una jerarquia de profundidad arbitraria.
End of explanation
feb_por_gen = feb.groupby(by='genero')
total_empleados = feb.salario.count()
feb_por_gen.salario.count().apply(lambda x: x/total_empleados)
Explanation: Proporción de la empleomanía por genero
Podemos realizar varios pasos tipo apply en hilo, inclusive con operaciones arbitrarias (funciones anonimas o lambdas)
End of explanation
total_nomina = feb.salario.sum()
feb_por_gen.salario.sum().apply(lambda x: x/total_nomina)
Explanation: Proporción de la nomina por genero
End of explanation
# esto es para que genere los graficos aqui dentro
%matplotlib inline
feb_por_gen.salario.sum().apply(lambda x: x/total_nomina).plot(kind='bar')
Explanation: Se fijaron bien?
Las mujeres son el 58.97% de la empleomanía y el 60.41% de la nómina. Mientras que los hombres son el 41.02% de la empleomanía y el 39.59% de la nómina.
Hmmm...
A graficar un poco
Resulta que con Pandas, podemos continuar el hilo de apply y convertir la tabla en un grafico de barra muy facilmente. En este caso, la proporción de la nómina asignada a hombres y mujeres.
End of explanation
import seaborn as sns
sns.countplot(x='genero',data=feb)
Explanation: Mejoremos el look un poco con Seaborn
La libreria de visualización Seaborn es:
* muy popular
* facil de usar
* mas inteligente
* se ve mas bonita por defecto que matplotlib (tan solo importarla cambia el estilo y colores de los graficos generados)
Diagrama de frecuencia de empleados mujeres y hombres
End of explanation
feb_por_gen.salario.sum().apply(lambda x: x/total_nomina).plot(kind='bar')
Explanation: Proporción de la nómina asignada a mujeres y hombres (reloaded)
Aquí vemos como el estilo del gráfico cambio solo por importar Seaborn. A mi me parece más bonito.
End of explanation
sns.distplot(feb.salario, kde=False)
Explanation: Histogramas del Salario
End of explanation
sns.FacetGrid(data=feb, col='genero', size=8).map(sns.distplot,'salario', kde=False)
Explanation: Histograma por genero (lado a lado)
End of explanation
sns.factorplot(data=feb, x='genero',y='salario',hue='genero', kind='box',size=6)
Explanation: Diagrama de cajas (box & whiskers)
End of explanation
import numpy as np
sns.distplot(np.random.normal(feb.salario.mean(),feb.salario.std(),feb.shape[0]))
Explanation: Una tangente (a)normal
Cómo se vería una distribución normal (gaussiana) si tuviera la media y desviación que vemos empíricamente en los datos?
Seaborn y Numpy al rescate!
End of explanation
feb_por_gen.salario.mean()
salario_promedio_f, salario_promedio_m = feb_por_gen.salario.mean()[['F','M']]
salario_promedio_f - salario_promedio_m
Explanation: Empecemos a enfocar nuestra exploración
Diference entre salario promedio por genero
End of explanation
salario_promedio_f/salario_promedio_m
(salario_promedio_f/salario_promedio_m - 1)*100
Explanation: Parece ser que el salario promedio de las mujeres supero en 2601.05 DOP al de los hombres...
Relacion salario mujeres y hombres
End of explanation
bottom25 = feb[feb.salario <= feb.salario.quantile(.25)]
bottom25_by_gender = bottom25.groupby(by='genero')
bottom25_by_gender.salario.describe()
bottom25_by_gender.salario.mean()['F'] - bottom25_by_gender.salario.mean()['M']
(bottom25_by_gender.salario.mean()['F']/bottom25_by_gender.salario.mean()['M'] - 1) * 100
Explanation: Sin controlar por ningun otro factor: en febrero de 2016 en la DGII, las mujeres en promedio ganaron aprox. 2601.05 DOP más que los hombres. El equivalente a un 6.16% más aprox.
Esto va en la misma linea que lo sugerido por las estadisticas publicas mencionadas aqui por Deloitte.
Que pasa cuando miramos los grupos que menos ganan?
End of explanation
sns.factorplot(data=bottom25, x='genero',y='salario',hue='genero', kind='box',size=8)
Explanation: En el primer cuartil de salarios la mujer promedio gano 4.30% (783.97 DOP) menos que el hombre promedio.
End of explanation
top25 = feb[feb.salario >= feb.salario.quantile(.75)]
top25_by_gender = top25.groupby(by='genero')
top25_by_gender.salario.describe()
top25_by_gender.salario.mean()['F'] - top25_by_gender.salario.mean()['M']
(top25_by_gender.salario.mean()['F']/top25_by_gender.salario.mean()['M'] - 1) * 100
Explanation: Que pasa cuando miramos los grupos que mas ganan?
End of explanation
sns.factorplot(data=top25, x='genero',y='salario',hue='genero', kind='box',size=6)
Explanation: En el ultimo cuartil la mujer promedio gano 9% (7294.20 DOP) menos que el hombre promedio. Pero, notan algo extraño?
End of explanation
trunc_top25 = feb[(feb.salario >= feb.salario.quantile(.75)) & (feb.salario < feb.salario.max())]
trunc_top25_by_gender = trunc_top25.groupby(by='genero')
trunc_top25_by_gender.salario.describe()
trunc_top25_by_gender.salario.mean()['F'] - trunc_top25_by_gender.salario.mean()['M']
(trunc_top25_by_gender.salario.mean()['F']/trunc_top25_by_gender.salario.mean()['M'] - 1) * 100
Explanation: Cual es el impacto de la persona que mas gana en la diferencia?
Outliers o valores extremos
End of explanation
sns.factorplot(data=trunc_top25, x='genero',y='salario',hue='genero', kind='box',size=6)
Explanation: Ahora la diferencia se redujo a 7.10% (5,632.26 DOP) menos en salario promedio para las mujeres que los hombres.
En este caso, a manera ilustrativa, consideramos que el salario más alto dista demasiado de los demás y su influencia distorsiona lo que queremos evaluar.
End of explanation
pd.set_option('mode.chained_assignment',None) # incantacion arcana que podemos ignorar por ahora
feb['salario_bin'] = pd.qcut(feb.salario,10,precision=0)
# guardemos esto para graficarlo mas abajo
epg_mean = pd.pivot_table(data=feb,index=['salario_bin'],columns=['genero'],values='salario',aggfunc=np.mean)
epg_mean
Explanation: Profundicemos de cuartiles a deciles
Veamos el comportamiento del salario promedio por genero para cada decil. Para eso necesitaremos:
importar a Numpy, solo para usar una funcion de promedio
crear una columna nueva que asigne cada record a un decil
Pivot Table! (igualito que en Excel)
End of explanation
from matplotlib import pyplot as plt
# Pandas nos genera el grafico inicial
ax = epg_mean.plot(grid=True,figsize=(10,8))
# Pero con matplotlib modificamos los nombres, las unidades y marcas de los ejes
ax.set_xlabel('Deciles de Salario')
ax.set_ylabel('Salario Promedio')
ticks = ax.set_xticklabels(ax.get_xticklabels(),rotation=45)
# Finalmente agregemos el promedio general como linea punteada para referencia
plt.axhline(feb.salario.mean(),linestyle='dashed')
Explanation: Graficamente es mas bonito
Seaborn es esteticamente más agradable y suele ahorrar mucho trabajo, los gráficos de Pandas se consiguen de la manera más facil; pero a veces es necesario modificar detalles que requieren usar matplotlib directamente.
End of explanation
spg = feb.groupby(by=['puesto_clean']).filter(\
                                              lambda x: \
                                              len(x) > 19 and \
                                                  len(x[x.genero == 'F']) > 0 and \
                                                  len(x[x.genero == 'M']) > 0)
print(spg.shape[0])
Explanation: Soy yo a las líneas están superpuestas en todos los deciles excepto el primero y el último?
Mismo trabajo = mismo sueldo?
Hasta ahora hemos estado mirando la nómina total, por género y por decil pero sin importar la posición.
Realmente es justo comparar los salarios entre diferentes puestos?
Miremos solamente los puestos que tienen 20+ empleados y por lo menos un hombre y una mujer (otro split-apply-combine)
End of explanation
spg.puesto_clean.nunique()
spg.puesto_clean.value_counts()
Explanation: Cuales puestos quedaron?
Y cuantos empleados hay en cada uno?
End of explanation
spg.groupby(by='genero').salario.describe()
sns.factorplot(data=spg, x='genero',y='salario',hue='genero', kind='box',size=6)
Explanation: Cómo se ve el salario en general por género de esta subpoblación?
End of explanation
spg_mean_pivot = pd.pivot_table(data=spg,values='salario',index=['puesto_clean'],columns=['genero'],aggfunc=np.mean)
spg_mean_pivot.sort_values('F',inplace=True)
spg_mean_pivot.head(10)
spg_mean_pivot.plot(kind='barh',figsize=(10,15))
Explanation: Y el salario para cada puesto por género?
Veamos los puestos ordenado de menor a mayor por el salario promedio de las mujeres que los ocupan.
End of explanation
spg_diff_pivot = spg_mean_pivot.apply(lambda x: x - x['M'], axis = 1)
spg_diff_pivot.sort_values('F',inplace=True)
spg_diff_pivot['F'].plot(kind='barh',figsize=(10,15))
spg_diff_pivot
Explanation: Calculemos la diferencia entre los promedios de cada puesto
Restandole al salario promedio de las mujeres el promedio de los hombres.
End of explanation
spg_rel_pivot = spg_mean_pivot.apply(lambda x: (x/x['M'] - 1) * 100, axis=1)
spg_rel_pivot['mas'] = spg_diff_pivot.F.map(lambda x: x > 0)
spg_rel_pivot.sort_values('F',inplace=True)
f = plt.figure(figsize=(12,12))
ax = sns.barplot(data=spg_rel_pivot,y=spg_rel_pivot.index,x='F',hue='mas',orient='h')
ax.set_xlabel('% diferencia promedio')
spg_rel_pivot
print("En {:d} de {:d} puestos el salario promedio de las mujeres es mayor que el de los hombres".format(spg_rel_pivot.mas.sum(), spg_rel_pivot.shape[0]))
Explanation: En terminos relativos (%)?
End of explanation
<END_TASK>