Estudio y análisis del funcionamiento del sistema educativo en Colombia.¶

Se importan las librerías necesarias para exploración, se definen ciertos parámetros de visualización de datos y se realiza la carga de la base de datos, obtenida del portal datos.co del gobierno colombiano.

In [1]:
# Importamos las librerías necesarias para el análisis
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
In [2]:
# Establecemos el tema darkgrid para las visualizaciones de seaborn
sns.set_theme(style = 'darkgrid')
In [3]:
# Iniciamos con la lectura de archivo .csv
df = pd.read_csv('Data/Estadisticas de educacion por departamento.csv')
# Se define la precisión de los flotantes a dos decimales para facilitar la lectura
pd.set_option('display.precision', 2)

df.head()
Out[3]:
AÑO CÓDIGO_DEPARTAMENTO DEPARTAMENTO POBLACIÓN_5_16 TASA_MATRICULACIÓN_5_16 COBERTURA_NETA COBERTURA_NETA_TRANSICIÓN COBERTURA_NETA_PRIMARIA COBERTURA_NETA_SECUNDARIA COBERTURA_NETA_MEDIA ... REPROBACIÓN REPROBACIÓN_TRANSICIÓN REPROBACIÓN_PRIMARIA REPROBACIÓN_SECUNDARIA REPROBACIÓN_MEDIA REPITENCIA REPITENCIA_TRANSICIÓN REPITENCIA_PRIMARIA REPITENCIA_SECUNDARIA REPITENCIA_MEDIA
0 2015 5 Antioquia 1262800 89.92 89.79 61.07 89.02 74.17 42.61 ... 6.84 0.20 5.44 10.56 5.64 2.83 0.20 2.26 4.55 1.95
1 2015 8 Atlántico 520783 86.17 85.92 53.52 82.12 74.28 45.61 ... 3.42 1.06 2.90 4.96 2.22 1.69 1.06 1.38 2.42 1.06
2 2015 11 Bogotá, D.C. 1455309 82.20 81.77 59.17 78.94 74.89 50.61 ... 0.09 0.00 0.03 0.12 0.23 9.91 0.00 6.49 16.02 7.94
3 2015 13 Bolívar 488886 88.78 88.69 58.50 87.33 71.05 39.34 ... 5.49 0.78 4.61 8.15 4.97 1.83 0.78 1.74 2.46 0.92
4 2015 15 Boyacá 284611 83.62 83.57 63.02 80.65 74.22 48.61 ... 4.51 0.29 2.97 7.09 4.29 2.27 0.29 1.46 3.68 2.07

5 rows × 37 columns

Se Modifican los nombres de las columnas y se unifican los datos de la columna 'Departamento'.

In [4]:
# Se modifican el formato de escritura de cada uno de los encabezados de columna para facilitar su lectura al momento de graficar
x_columns = list(df.columns)
y_columns = []

for i in x_columns:
    y_columns.append(i.capitalize().replace('_',' '))
    
df.columns = y_columns
df.head()
Out[4]:
Año Código departamento Departamento Población 5 16 Tasa matriculación 5 16 Cobertura neta Cobertura neta transición Cobertura neta primaria Cobertura neta secundaria Cobertura neta media ... Reprobación Reprobación transición Reprobación primaria Reprobación secundaria Reprobación media Repitencia Repitencia transición Repitencia primaria Repitencia secundaria Repitencia media
0 2015 5 Antioquia 1262800 89.92 89.79 61.07 89.02 74.17 42.61 ... 6.84 0.20 5.44 10.56 5.64 2.83 0.20 2.26 4.55 1.95
1 2015 8 Atlántico 520783 86.17 85.92 53.52 82.12 74.28 45.61 ... 3.42 1.06 2.90 4.96 2.22 1.69 1.06 1.38 2.42 1.06
2 2015 11 Bogotá, D.C. 1455309 82.20 81.77 59.17 78.94 74.89 50.61 ... 0.09 0.00 0.03 0.12 0.23 9.91 0.00 6.49 16.02 7.94
3 2015 13 Bolívar 488886 88.78 88.69 58.50 87.33 71.05 39.34 ... 5.49 0.78 4.61 8.15 4.97 1.83 0.78 1.74 2.46 0.92
4 2015 15 Boyacá 284611 83.62 83.57 63.02 80.65 74.22 48.61 ... 4.51 0.29 2.97 7.09 4.29 2.27 0.29 1.46 3.68 2.07

5 rows × 37 columns

Se eliminan los acentos y se cambia los nombres de algunas ciudades que cuentan con diferencias de redacción, esto con el fin de unificar los datos.

In [5]:
x_departamento = list(df['Departamento'])
y_departamento = []

for i in x_departamento:
    y_departamento.append(i.replace('á', 'a').replace('é', 'e').replace('í', 'i').replace('ó', 'o').replace('ú', 'u')
                         .replace('Valle', 'Valle del Cauca').replace('Valle del Cauca del Cauca', 'Valle del Cauca').replace('Norte Santander', 'Norte de Santander')
                         .replace('Bogota, D.C.', 'Bogota D.C.').replace('Bogota', 'Bogota D.C.').replace('Bogota D.C. D.C.', 'Bogota D.C.')
                         .replace('Archipielago de San Andres. Providencia y Santa Catalina', 'Arch. de S.Andres,\nProv., S.Catalina')
                         .replace('San Andres', 'Arch. de S.Andres,\nProv., S.Catalina')
                         .replace('Archipielago de Arch. de S.Andres,\nProv., S.Catalina, Providencia y Santa Catalina', 'Arch. de S.Andres,\nProv., S.Catalina')
                         )
    
df['Departamento'] = pd.Series(y_departamento)

Se eliminan las columnas que en primera instancia se pueden clasificar como innecesarias o irrelevantes para el estudio, en este caso el código del departamento.

In [6]:
df = df.drop('Código departamento', axis = 'columns')

Se realiza una corrección a los datos de las filas del año 2021 ya que sus valores no estaban en formato porcentual, así que se multiplican las columnas por 100 para estandarizar los datos.

In [7]:
index_2021 = df[df['Año'] == 2021].index
df.iloc[index_2021, 3:] = df.iloc[index_2021, 3:] * 100

Validacion de datos¶

¿Qué tipo de dato son las variables del conjunto de datos?¶

In [8]:
df.dtypes
Out[8]:
Año                              int64
Departamento                    object
Población 5 16                   int64
Tasa matriculación 5 16        float64
Cobertura neta                 float64
Cobertura neta transición      float64
Cobertura neta primaria        float64
Cobertura neta secundaria      float64
Cobertura neta media           float64
Cobertura bruta                float64
Cobertura bruta transición     float64
Cobertura bruta primaria       float64
Cobertura bruta secundaria     float64
Cobertura bruta media          float64
Tamaño promedio de grupo       float64
Sedes conectadas a internet    float64
Deserción                      float64
Deserción transición           float64
Deserción primaria             float64
Deserción secundaria           float64
Deserción media                float64
Aprobación                     float64
Aprobación transición          float64
Aprobación primaria            float64
Aprobación secundaria          float64
Aprobación media               float64
Reprobación                    float64
Reprobación transición         float64
Reprobación primaria           float64
Reprobación secundaria         float64
Reprobación media              float64
Repitencia                     float64
Repitencia transición          float64
Repitencia primaria            float64
Repitencia secundaria          float64
Repitencia media               float64
dtype: object

¿Cuántas variables de cada tipo de dato tenemos en el conjunto de datos?¶

In [9]:
df.dtypes.value_counts()
Out[9]:
float64    33
int64       2
object      1
dtype: int64

¿Cuántas variables y observaciones tenemos en el conjunto de datos?¶

In [10]:
df.shape
Out[10]:
(363, 36)

¿Existen valores nulos explícitos en el conjunto de datos?¶

In [11]:
valor_nulo = df.isna().any().sort_values(ascending = False)
valor_nulo
Out[11]:
Deserción transición            True
Sedes conectadas a internet     True
Tamaño promedio de grupo        True
Año                            False
Reprobación                    False
Aprobación transición          False
Aprobación primaria            False
Aprobación secundaria          False
Aprobación media               False
Reprobación transición         False
Deserción media                False
Reprobación primaria           False
Reprobación secundaria         False
Reprobación media              False
Repitencia                     False
Repitencia transición          False
Repitencia primaria            False
Repitencia secundaria          False
Aprobación                     False
Deserción primaria             False
Deserción secundaria           False
Departamento                   False
Deserción                      False
Cobertura bruta media          False
Cobertura bruta secundaria     False
Cobertura bruta primaria       False
Cobertura bruta transición     False
Cobertura bruta                False
Cobertura neta media           False
Cobertura neta secundaria      False
Cobertura neta primaria        False
Cobertura neta transición      False
Cobertura neta                 False
Tasa matriculación 5 16        False
Población 5 16                 False
Repitencia media               False
dtype: bool

De tener observaciones con valores nulos, ¿cuántas tenemos por cada variable?¶

In [12]:
df.isna().sum().sort_values(ascending = False).head()
Out[12]:
Sedes conectadas a internet    132
Tamaño promedio de grupo       132
Deserción transición             1
Año                              0
Reprobación                      0
dtype: int64

¿Cuál es la proporción de valores nulos por cada variable?¶

In [13]:
(
    df
    .loc[:, ['Deserción transición', 'Sedes conectadas a internet', 'Tamaño promedio de grupo']]
    .isna()
    .melt(var_name='Category', value_name='Values')
    .pipe(
        lambda df:(
            sns.displot(
                data = df,
                y = 'Category',
                hue = 'Values',
                multiple = 'fill',
                aspect = 2
            )
        )
    )
)
plt.show()
No description has been provided for this image

¿Cuántas observaciones perdemos si eliminamos los datos faltantes?¶

In [14]:
len(df.index[df['Deserción transición'].isna() | df['Sedes conectadas a internet'].isna() | df['Tamaño promedio de grupo'].isna()])
Out[14]:
133

Segmentación de los datos para facilitar su manejo¶

Se segmenta la base de datos en sus 5 categorías principales: datos generales, transición, primaria, secundaria y media

In [15]:
df_general = df.loc[:, ['Año', 'Departamento', 'Población 5 16', 'Tasa matriculación 5 16', 'Cobertura neta', 'Cobertura bruta', 'Deserción media', 'Aprobación media', 'Reprobación media', 'Repitencia media']]
In [16]:
nivel_educativo = ['transición', 'primaria', 'secundaria', 'media']
dataframes = {}

for nivel in nivel_educativo:
    cols = [f'Año', f'Departamento', f'Cobertura neta {nivel}', f'Cobertura bruta {nivel}',
            f'Deserción {nivel}', f'Aprobación {nivel}', f'Reprobación {nivel}', f'Repitencia {nivel}']
    dataframes[nivel] = df.loc[:, cols]

df_transicion = dataframes.get('transición', None)
df_primaria = dataframes.get('primaria', None)
df_secundaria = dataframes.get('secundaria', None)
df_media = dataframes.get('media', None)

Conteos y proporciones¶

Estadísticos que describen el conjunto de datos de forma general¶

In [17]:
df.describe(exclude = 'object').T.round(2)
Out[17]:
count mean std min 25% 50% 75% max
Año 363.0 2016.00 3.17 2011.00 2013.00 2016.00 2019.00 2.02e+03
Población 5 16 363.0 303772.53 316233.64 10853.00 88314.50 237991.00 390953.50 1.48e+06
Tasa matriculación 5 16 363.0 85.10 10.48 52.33 79.47 86.36 93.31 1.04e+02
Cobertura neta 363.0 85.53 10.59 50.79 80.47 87.37 93.43 1.04e+02
Cobertura neta transición 363.0 56.27 11.59 19.22 49.94 57.80 65.07 7.92e+01
Cobertura neta primaria 363.0 83.91 10.14 51.12 78.35 85.84 91.45 1.02e+02
Cobertura neta secundaria 363.0 67.59 15.46 24.06 59.73 72.48 77.37 9.11e+01
Cobertura neta media 363.0 37.32 12.26 6.79 29.84 40.46 46.22 5.93e+01
Cobertura bruta 363.0 98.22 11.52 59.79 93.53 100.22 105.97 1.23e+02
Cobertura bruta transición 363.0 89.18 17.66 32.03 80.46 88.69 97.82 1.45e+02
Cobertura bruta primaria 363.0 108.46 13.06 72.05 100.93 109.09 116.78 1.51e+02
Cobertura bruta secundaria 363.0 99.27 15.93 43.77 92.94 103.16 110.14 1.26e+02
Cobertura bruta media 363.0 74.40 16.39 23.92 65.86 78.46 85.60 1.06e+02
Tamaño promedio de grupo 231.0 6162.28 11036.63 13.21 22.36 26.31 54.26 3.22e+04
Sedes conectadas a internet 231.0 34.90 21.37 0.00 20.26 30.33 42.26 1.00e+02
Deserción 363.0 3.99 1.83 0.46 2.76 3.69 4.84 1.09e+01
Deserción transición 362.0 4.02 2.22 0.29 2.57 3.65 5.00 2.08e+01
Deserción primaria 363.0 3.38 1.71 0.34 2.21 3.11 4.00 1.07e+01
Deserción secundaria 363.0 4.98 2.35 0.38 3.40 4.63 6.23 1.32e+01
Deserción media 363.0 3.74 2.39 0.42 2.48 3.18 4.28 2.99e+01
Aprobación 363.0 90.58 4.71 72.00 88.62 90.77 93.84 9.91e+01
Aprobación transición 363.0 95.08 3.13 76.88 94.33 95.67 96.83 1.00e+02
Aprobación primaria 363.0 91.98 4.81 70.72 90.65 92.63 95.06 9.91e+01
Aprobación secundaria 363.0 87.50 5.93 65.14 83.74 87.46 92.10 9.90e+01
Aprobación media 363.0 91.24 4.36 62.63 89.29 91.76 93.94 9.95e+01
Reprobación 363.0 5.44 3.81 0.00 2.43 5.47 7.48 1.93e+01
Reprobación transición 363.0 0.92 1.71 0.00 0.16 0.42 0.89 1.31e+01
Reprobación primaria 363.0 4.65 4.01 0.00 1.83 4.06 6.00 2.28e+01
Reprobación secundaria 363.0 7.52 4.89 0.00 3.54 7.94 10.80 2.46e+01
Reprobación media 363.0 5.03 3.07 0.00 2.62 5.00 6.79 1.79e+01
Repitencia 363.0 3.01 2.26 0.10 1.30 2.26 4.11 1.48e+01
Repitencia transición 363.0 0.92 1.71 0.00 0.16 0.42 0.89 1.31e+01
Repitencia primaria 363.0 2.77 2.32 0.06 1.18 1.96 3.71 1.90e+01
Repitencia secundaria 363.0 4.07 3.06 0.11 1.87 3.24 5.48 2.52e+01
Repitencia media 363.0 1.74 1.55 0.00 0.77 1.34 2.26 1.64e+01

Analisis de datos para los estudiantes de transición¶

Se aprecia en los mapas de calor que no hay un gran coeficiente de relación positivo entre las variables dispuestas en la base de datos exceptuando:

Trnasición:

  • Reprobación con la repitencia (1 para las dos).
  • Cobertura neta con la cobertura bruta (0.69 para las dos)

Primaria:

  • Cobertura neta con la cobertura bruta (0.66 para las dos)

Secundaria:

De la misma forma se ve un gran coeficiente de relación negativa con:

Transición:

  • Aprobación con deserción (-0.84), reprobación y repitencia (-0.74 para las dos)

Primaria

  • Aprobación con deserción (-0.61) y reprobación (-0.94)
In [18]:
#Se define el tamaño para cada figura y el número de parcelaciones
fig, ax = plt.subplots(2, 2, sharey = True, figsize = [13,13])

dataframes = [(df_transicion, 'Transición'), (df_primaria, 'Primaria'), (df_secundaria, 'Secundaria'), (df_media, 'Media')]
labels = ['Cobertura\nneta', 'Cobertura\nbruta', 'Deserción', 'Aprobación', 'Reprobación', 'Repitencia']

for i, y in enumerate(dataframes):
    sns.heatmap(data = y[0].iloc[:, 2:].corr(), annot = True, ax = ax[i//2, i%2])    
    ax[i//2, i%2].set(title = y[1], xticklabels = labels, yticklabels = labels)

fig.suptitle('Correlación de variables por nivel academico')
plt.subplots_adjust(top = 0.925, hspace = 0.3)
plt.show()
No description has been provided for this image

Ya que la cobertura neta es el dato óptimo para saber el estado actual del alcance de la educación en las regiones se realizará un scatterplot para ver la incidencia que esta variable tiene con respecto a la aprobación y reprobación a lo largo del tiempo.

In [19]:
#Se define el tamaño para cada figura y el número de parcelaciones
fig, ax = plt.subplots(4, 2, sharex = True, figsize = [11,11])

dataframes = [(df_transicion, 'transición'), (df_primaria, 'primaria'), (df_secundaria, 'secundaria'), (df_media, 'media')]

for i, y in enumerate(dataframes):
    sns.scatterplot(
        data = y[0], x = f'Cobertura neta {y[1]}', y = f'Aprobación {y[1]}',
        hue = 'Año', legend = False, palette = 'crest', ax = ax[i,0])    
    ax[i,0].set(title = f'Aprobación {y[1]}', ylabel = '% de aprobación')
    
    sns.scatterplot(
        data = y[0], x = f'Cobertura neta {y[1]}', y = f'Reprobación {y[1]}',
        hue = 'Año', legend = False, ax = ax[i,1])    
    ax[i,1].set(title = f'Reprobación {y[1]}', ylabel = '% de reprobación')

#**************************************************************************************
    
sns.scatterplot(
    data = df_transicion, x = 'Cobertura neta transición', y = 'Aprobación transición',
    hue = 'Año', legend = list(range(2011, 2022)), palette = 'crest', ax = ax[0,0])

sns.scatterplot(
    data = df_transicion, x = 'Cobertura neta transición', y = 'Reprobación transición',
    hue = 'Año', legend = list(range(2011, 2022)), ax = ax[0,1])    

#**************************************************************************************

sns.move_legend(ax[0,0], "upper right", bbox_to_anchor=(-0.2, 1.05))
sns.move_legend(ax[0,1], "upper left", bbox_to_anchor=(1.05, 1.05))
sns.color_palette("mako", as_cmap=True)
fig.suptitle('Cobertura neta vs aprobación / reprobación por nivel academico')
plt.subplots_adjust(top = 0.925, hspace = 0.2)
plt.show()
No description has been provided for this image

Se crea un gráfico de líneas para entender la evolución de la cobertura neta a través del tiempo por cada nivel educativo.

In [20]:
#Se define el tamaño para cada figura y el número de parcelaciones
fig, ax = plt.subplots(1, 1, figsize = [7,5])
nivel_educativo = ['transición', 'primaria', 'secundaria', 'media']
lista_dataframe = [df_transicion, df_primaria, df_secundaria, df_media]

for x in nivel_educativo:
    sns.lineplot(
        data = lista_dataframe[nivel_educativo.index(x)], x = 'Año', y = f'Cobertura neta {x}',
        label = f'{x}'
    )

fig.suptitle('Cobertura neta vs años por nivel academico')
ax.set_xlabel('Año')
ax.set_ylabel('% de cobertura neta')
plt.gca().set_xticks(list(range(2011, 2022)))
plt.xticks(rotation = 45)
plt.legend(loc = 'upper right', bbox_to_anchor=(1.3, 1.02))
plt.show()
No description has been provided for this image
In [21]:
df_transicion_dept = df_transicion.groupby('Departamento', as_index = False).agg('median')
df_primaria_dept = df_primaria.groupby('Departamento', as_index = False).agg('median')
df_secundaria_dept = df_secundaria.groupby('Departamento', as_index = False).agg('median')
df_media_dept = df_media.groupby('Departamento', as_index = False).agg('median')
In [22]:
#Se define el tamaño para cada figura y el número de parcelaciones [15,21]
fig, ax = plt.subplots(4, 2, sharex = True, figsize = [15,15])

dataframes = [(df_transicion_dept, 'transición'), (df_primaria_dept, 'primaria'), (df_secundaria_dept, 'secundaria'), (df_media_dept, 'media')]

for i, y in enumerate(dataframes):
    sns.barplot(
        data = y[0].sort_values(f'Aprobación {y[1]}', ascending = False).head(),
        x = f'Aprobación {y[1]}', y = 'Departamento', ax = ax[i,0])
    ax[i,0].set(xlabel = '', title = f'Aprobación {y[1]}')

    sns.barplot(
        data = y[0].sort_values(f'Reprobación {y[1]}', ascending = False).head(),
        x = f'Reprobación {y[1]}', y = 'Departamento', ax = ax[i,1])
    ax[i,1].set(xlabel = '', title = f'Reprobación {y[1]}')

ax[3,0].set(xlabel = '% de aprobación', title = 'Aprobación media')
ax[3,1].set(xlabel = '% de reprobación', title = 'Reprobación media')
    
#**************************************************************************************

fig.suptitle('Aprobación / reprobación en cada Departamento por nivel academico')
plt.subplots_adjust(top = 0.93, wspace = 0.3)
plt.show()
No description has been provided for this image
In [23]:
sns.relplot(
    data = df.groupby('Año').agg('median'),
    x = 'Año',
    y = 'Deserción transición',
    kind = 'line'
)
/tmp/ipykernel_20/4011081657.py:2: FutureWarning: The default value of numeric_only in DataFrameGroupBy.median is deprecated. In a future version, numeric_only will default to False. Either specify numeric_only or select only columns which should be valid for the function.
  data = df.groupby('Año').agg('median'),
Out[23]:
<seaborn.axisgrid.FacetGrid at 0x7af2c8383d90>
No description has been provided for this image
In [24]:
sns.relplot(
    data = df.groupby('Año').agg('sum'),
    x = 'Año',
    y = 'Población 5 16',  
    kind = 'line'
)
sns.relplot(
    data = df.groupby('Año').agg('median'),
    x = 'Año',
    y = 'Tasa matriculación 5 16',
    kind = 'line'
)
/tmp/ipykernel_20/4256122107.py:2: FutureWarning: The default value of numeric_only in DataFrameGroupBy.sum is deprecated. In a future version, numeric_only will default to False. Either specify numeric_only or select only columns which should be valid for the function.
  data = df.groupby('Año').agg('sum'),
/tmp/ipykernel_20/4256122107.py:8: FutureWarning: The default value of numeric_only in DataFrameGroupBy.median is deprecated. In a future version, numeric_only will default to False. Either specify numeric_only or select only columns which should be valid for the function.
  data = df.groupby('Año').agg('median'),
Out[24]:
<seaborn.axisgrid.FacetGrid at 0x7af2c619c550>
No description has been provided for this image
No description has been provided for this image
In [25]:
sns.catplot(data = df, x = 'Año', y = 'Tasa matriculación 5 16', kind = 'bar')
Out[25]:
<seaborn.axisgrid.FacetGrid at 0x7af2c619cf40>
No description has been provided for this image
In [26]:
df.isnull().sum()
Out[26]:
Año                              0
Departamento                     0
Población 5 16                   0
Tasa matriculación 5 16          0
Cobertura neta                   0
Cobertura neta transición        0
Cobertura neta primaria          0
Cobertura neta secundaria        0
Cobertura neta media             0
Cobertura bruta                  0
Cobertura bruta transición       0
Cobertura bruta primaria         0
Cobertura bruta secundaria       0
Cobertura bruta media            0
Tamaño promedio de grupo       132
Sedes conectadas a internet    132
Deserción                        0
Deserción transición             1
Deserción primaria               0
Deserción secundaria             0
Deserción media                  0
Aprobación                       0
Aprobación transición            0
Aprobación primaria              0
Aprobación secundaria            0
Aprobación media                 0
Reprobación                      0
Reprobación transición           0
Reprobación primaria             0
Reprobación secundaria           0
Reprobación media                0
Repitencia                       0
Repitencia transición            0
Repitencia primaria              0
Repitencia secundaria            0
Repitencia media                 0
dtype: int64
In [27]:
df_v = df[df['Departamento'] == 'Valle del Cauca']
df_v.head()
Out[27]:
Año Departamento Población 5 16 Tasa matriculación 5 16 Cobertura neta Cobertura neta transición Cobertura neta primaria Cobertura neta secundaria Cobertura neta media Cobertura bruta ... Reprobación Reprobación transición Reprobación primaria Reprobación secundaria Reprobación media Repitencia Repitencia transición Repitencia primaria Repitencia secundaria Repitencia media
23 2015 Valle del Cauca 875476 84.44 84.26 50.96 82.63 69.59 39.64 96.74 ... 6.18 0.69 4.62 9.70 4.99 0.92 0.69 0.72 1.44 0.60
56 2014 Valle del Cauca 880625 85.52 85.34 53.64 83.48 70.81 39.12 98.40 ... 2.24 0.18 1.59 3.61 2.14 0.82 0.18 0.81 1.06 0.52
89 2013 Valle del Cauca 887988 87.56 87.37 58.92 84.98 71.27 40.61 101.44 ... 3.39 0.25 2.59 5.13 3.52 1.30 0.25 1.09 1.90 0.86
122 2012 Valle del Cauca 894698 88.26 88.09 60.32 86.16 71.21 40.62 101.86 ... 3.29 0.20 2.34 5.28 3.33 1.64 0.20 1.39 2.40 1.01
155 2011 Valle del Cauca 906602 88.51 88.33 56.25 86.83 72.17 42.06 101.50 ... 5.07 0.58 3.32 7.90 6.37 2.30 0.58 2.09 3.22 1.09

5 rows × 36 columns

In [28]:
sns.catplot(data = df_v, x = 'Año', y = 'Tasa matriculación 5 16', kind = 'bar')
Out[28]:
<seaborn.axisgrid.FacetGrid at 0x7af2c6049900>
No description has been provided for this image