Está en la página 1de 20

8/6/22, 10:42 contaminazmvt - Jupyter Notebook

Contaminación Zona Metropolitana del Valle de


Toluca
Optativa de Programación ECATSIG

Jose Miguel Muñoz Rodriguez


Facultad de Geografía

Universidad Autónoma del Estado de México

In [1]: # Importamos las librerías de Pandas Data Frame para realizar análisis de datos
import pandas as pd

# Cargar los datos en una estructura de pandas
datos = pd.read_csv('datos1/contaminazmvt.csv', sep = '|')

# Se crea el dataframe de pandas
df = pd.DataFrame(datos)

#Visualizar datos del dataframe - Entre parentesis se coloca el número de datos
df.head(6)

#Geopandas es una libreria que incorpora datos espaciales

#GDAL - Libreria de python para datos raster

#RASTERING - Libreria de python para datos raster

Out[1]:
FECHA PM10 PM25 O3 NO2 CO SO2 MAXIMO CONTAMINANTE ESTACION ZONA

0 01/01/2021 160 221.0 43 25 26 5 221 PM2.5 SC ZMVT

1 02/01/2021 143 203.0 47 23 11 5 203 PM2.5 SC ZMVT

2 03/01/2021 116 111.0 42 22 14 5 116 PM10 SC ZMVT

3 04/01/2021 111 104.0 76 28 12 5 111 PM10 SC ZMVT

4 05/01/2021 115 99.0 67 29 16 5 115 PM10 AJ ZMVT

5 06/01/2021 116 102.0 44 28 19 6 116 PM10 SC ZMVT

In [2]: #Muestra el número de renglones y columnas


df.shape

Out[2]: (4018, 11)

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 1/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [3]: #Muestra la informacion del dataset


df.info

Out[3]: <bound method DataFrame.info of FECHA PM10 PM25 O3 NO2 CO SO2


MAXIMO CONTAMINANTE ESTACION \

0 01/01/2021 160 221.0 43 25 26 5 221 PM2.5 SC


1 02/01/2021 143 203.0 47 23 11 5 203 PM2.5 SC
2 03/01/2021 116 111.0 42 22 14 5 116 PM10 SC
3 04/01/2021 111 104.0 76 28 12 5 111 PM10 SC
4 05/01/2021 115 99.0 67 29 16 5 115 PM10 AJ
... ... ... ... .. ... .. ... ... ... ...
4013 26/09/2011 67 NaN 61 25 17 8 67 PM10 AP
4014 27/09/2011 71 NaN 73 31 23 8 73 O3 SM
4015 28/09/2011 85 NaN 67 25 16 14 85 PM10 SC
4016 29/09/2011 77 NaN 63 31 24 11 77 PM10 SC
4017 30/09/2011 76 NaN 55 28 24 12 76 PM10 SC

ZONA

0 ZMVT

1 ZMVT

2 ZMVT

3 ZMVT

4 ZMVT

... ...

4013 NORTE

4014 SUR

4015 NORTE

4016 NORTE

4017 NORTE

[4018 rows x 11 columns]>

In [4]: #Buscar valores duplicados


df.duplicated()

Out[4]: 0 False

1 False

2 False

3 False

4 False

...

4013 False

4014 False

4015 False

4016 False

4017 False

Length: 4018, dtype: bool

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 2/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [5]: #Verificar renglones nulos


df.isna().sum()

Out[5]: FECHA 0

PM10 0

PM25 1673

O3 0

NO2 0

CO 0

SO2 0

MAXIMO 0

CONTAMINANTE 0

ESTACION 1

ZONA 0

dtype: int64

PM10: Partículas PM10

PM25: Partículas PM2.5

O3: OZONO

NO2: Ióxido de Nitrógeno

SO2: Dióxido de Azúfre

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 3/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [6]: # Debido a que la fecha no está en un formato adecuado, vamos a convertirla a tip
# corce forza la conversion

df['FECHA'] = pd.to_datetime(df['FECHA'], errors = 'coerce')
df.info()

<class 'pandas.core.frame.DataFrame'>

RangeIndex: 4018 entries, 0 to 4017

Data columns (total 11 columns):

# Column Non-Null Count Dtype

--- ------ -------------- -----

0 FECHA 4018 non-null datetime64[ns]

1 PM10 4018 non-null int64

2 PM25 2345 non-null float64

3 O3 4018 non-null int64

4 NO2 4018 non-null int64

5 CO 4018 non-null int64

6 SO2 4018 non-null int64

7 MAXIMO 4018 non-null int64

8 CONTAMINANTE 4018 non-null object

9 ESTACION 4017 non-null object

10 ZONA 4018 non-null object

dtypes: datetime64[ns](1), float64(1), int64(6), object(3)

memory usage: 345.4+ KB

In [7]: df.head()

Out[7]:
FECHA PM10 PM25 O3 NO2 CO SO2 MAXIMO CONTAMINANTE ESTACION ZONA

0 2021-01-01 160 221.0 43 25 26 5 221 PM2.5 SC ZMVT

1 2021-02-01 143 203.0 47 23 11 5 203 PM2.5 SC ZMVT

2 2021-03-01 116 111.0 42 22 14 5 116 PM10 SC ZMVT

3 2021-04-01 111 104.0 76 28 12 5 111 PM10 SC ZMVT

4 2021-05-01 115 99.0 67 29 16 5 115 PM10 AJ ZMVT

ESTADISTICA DESCRIPTIVA

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 4/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [8]: #describe toma los valores numéricos y me genera las metricas basicas de la estad
#Matriz traspuesta
df.describe().T

Out[8]:
count mean std min 25% 50% 75% max

PM10 4018.0 89.084868 31.311583 14.0 64.0 95.0 112.0 328.0

PM25 2345.0 98.463113 21.814756 54.0 82.0 99.0 109.0 277.0

O3 4018.0 60.166750 22.617207 15.0 43.0 57.0 76.0 136.0

NO2 4018.0 28.530612 9.963248 7.0 21.0 27.0 34.0 88.0

CO 4018.0 17.374316 6.306799 5.0 13.0 17.0 21.0 65.0

SO2 4018.0 9.078397 4.018327 3.0 6.0 8.0 11.0 40.0

MAXIMO 4018.0 96.210553 27.985326 23.0 76.0 100.0 114.0 328.0

In [9]: # Datos de año 2020 y 2021


filtro1 = df[df['FECHA'] >= '01/01/2020']
filtro1.head()

Out[9]:
FECHA PM10 PM25 O3 NO2 CO SO2 MAXIMO CONTAMINANTE ESTACION ZONA

0 2021-01-01 160 221.0 43 25 26 5 221 PM2.5 SC ZMVT

1 2021-02-01 143 203.0 47 23 11 5 203 PM2.5 SC ZMVT

2 2021-03-01 116 111.0 42 22 14 5 116 PM10 SC ZMVT

3 2021-04-01 111 104.0 76 28 12 5 111 PM10 SC ZMVT

4 2021-05-01 115 99.0 67 29 16 5 115 PM10 AJ ZMVT

In [10]: #Datos de los años 2020 y 2021 pero solamente algunas columnas
filtro2 = df[df['FECHA'] >= '01/01/2020'][['FECHA', 'PM25', 'PM10', 'O3', 'NO2',
filtro2.head()

Out[10]:
FECHA PM25 PM10 O3 NO2 CO SO2

0 2021-01-01 221.0 160 43 25 26 5

1 2021-02-01 203.0 143 47 23 11 5

2 2021-03-01 111.0 116 42 22 14 5

3 2021-04-01 104.0 111 76 28 12 5

4 2021-05-01 99.0 115 67 29 16 5

Calculamos un resumen de particulas PM2.5 por año para verificar los


años mas contaminantes

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 5/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [11]: #Agregamos una columna nueve al dataframe que contenga el año


df['AÑO'] = pd.DatetimeIndex(df['FECHA']).year
df.head()

Out[11]:
FECHA PM10 PM25 O3 NO2 CO SO2 MAXIMO CONTAMINANTE ESTACION ZONA AÑO

2021-
0 160 221.0 43 25 26 5 221 PM2.5 SC ZMVT 2021
01-01

2021-
1 143 203.0 47 23 11 5 203 PM2.5 SC ZMVT 2021
02-01

2021-
2 116 111.0 42 22 14 5 116 PM10 SC ZMVT 2021
03-01

2021-
3 111 104.0 76 28 12 5 111 PM10 SC ZMVT 2021
04-01

2021-
4 115 99.0 67 29 16 5 115 PM10 AJ ZMVT 2021
05-01

In [12]: #Generamos un agrupamiento de PM25


grupo_anio = pd.DataFrame(df.groupby('AÑO')['PM25'].mean())
grupo_anio.sort_values(by='PM25', ascending = False).head(11)

Out[12]:
PM25

AÑO

2017 104.558904

2016 103.513661

2018 97.202740

2019 96.997260

2020 95.527322

2015 95.032680

2021 94.410959

2011 NaN

2012 NaN

2013 NaN

2014 NaN

Insight: Los años 2016, 2017, 2018 y 2019 han sido los más
contaminados por particular PMT 2.5

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 6/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [13]: #Generamos un agrupamiento para PM10


grupo_anio = pd.DataFrame(df.groupby('AÑO')['PM10'].mean())
grupo_anio.sort_values(by='PM10', ascending = False).head(12)

Out[13]:
PM10

AÑO

2017 97.767123

2018 97.564384

2021 97.326027

2019 97.016438

2016 93.568306

2011 93.545205

2020 93.038251

2015 90.383562

2014 75.671233

2013 72.082192

2012 71.994536

In [14]: #Meses mas contaminados por PM 2.5


#Agregamos el mes al dataframe
df['MES'] = pd.DatetimeIndex(df['FECHA']).month
df.head()

Out[14]:
FECHA PM10 PM25 O3 NO2 CO SO2 MAXIMO CONTAMINANTE ESTACION ZONA AÑO

2021-
0 160 221.0 43 25 26 5 221 PM2.5 SC ZMVT 2021
01-01

2021-
1 143 203.0 47 23 11 5 203 PM2.5 SC ZMVT 2021
02-01

2021-
2 116 111.0 42 22 14 5 116 PM10 SC ZMVT 2021
03-01

2021-
3 111 104.0 76 28 12 5 111 PM10 SC ZMVT 2021
04-01

2021-
4 115 99.0 67 29 16 5 115 PM10 AJ ZMVT 2021
05-01

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 7/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [15]: #Generamos un agrupamiento para PM25


grupo_mes = pd.DataFrame(df.groupby('MES')['PM25'].mean())
grupo_mes.sort_values(by='PM25', ascending = False).head(12)

Out[15]:
PM25

MES

12 115.923810

1 110.172775

2 107.428571

4 104.972973

5 101.083770

11 100.344828

3 99.240838

7 90.476440

10 88.966667

8 88.785714

9 88.162562

6 87.302703

Insight: Los meses mas contaminados son Diciembre y


Enero
In [16]: #Dias mas contaminados por PM 2.5
#Agregamos el dia al dataframe
df['DIA'] = pd.DatetimeIndex(df['FECHA']).day
df.head()

Out[16]:
FECHA PM10 PM25 O3 NO2 CO SO2 MAXIMO CONTAMINANTE ESTACION ZONA AÑO

2021-
0 160 221.0 43 25 26 5 221 PM2.5 SC ZMVT 2021
01-01

2021-
1 143 203.0 47 23 11 5 203 PM2.5 SC ZMVT 2021
02-01

2021-
2 116 111.0 42 22 14 5 116 PM10 SC ZMVT 2021
03-01

2021-
3 111 104.0 76 28 12 5 111 PM10 SC ZMVT 2021
04-01

2021-
4 115 99.0 67 29 16 5 115 PM10 AJ ZMVT 2021
05-01

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 8/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [17]: #Generamos un agrupamiento para PM25


grupo_dia = pd.DataFrame(df.groupby('DIA')['PM25'].mean())
grupo_dia.sort_values(by='PM25', ascending = False).head(12)

Out[17]:
PM25

DIA

1 129.166667

12 111.464286

2 110.375000

5 110.041667

25 106.766234

3 105.000000

26 103.519481

4 102.861111

24 102.038961

16 99.584416

31 98.755556

28 98.571429

Insight: Los dias 1, 12 y 2 son los mas contaminados


In [18]: #Generamos un histograma de frecuencias a la columna PM25
df['PM25'].hist()

Out[18]: <AxesSubplot:>

Los valores de particulas PM2.5 se concentran entre 53 hasta 270 aproximadamente

Las concentraciones mayores estan entre 75 y 125 ppm

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 9/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [19]: #### Podemos generar clases de los valores de PM2.5 mediante el método cut
pd.cut(df['PM25'], bins = 5).value_counts()

Out[19]: (53.777, 98.6] 1168

(98.6, 143.2] 1124

(143.2, 187.8] 35

(187.8, 232.4] 12

(232.4, 277.0] 6

Name: PM25, dtype: int64

In [20]: #Verificar renglones nulos


df.isna().sum()

Out[20]: FECHA 0

PM10 0

PM25 1673

O3 0

NO2 0

CO 0

SO2 0

MAXIMO 0

CONTAMINANTE 0

ESTACION 1

ZONA 0

AÑO 0

MES 0

DIA 0

dtype: int64

In [21]: df.count()

Out[21]: FECHA 4018

PM10 4018

PM25 2345

O3 4018

NO2 4018

CO 4018

SO2 4018

MAXIMO 4018

CONTAMINANTE 4018

ESTACION 4017

ZONA 4018

AÑO 4018

MES 4018

DIA 4018

dtype: int64

In [22]: (1673/2345)*100
## Falta el 29% de valores de PM 2.5

Out[22]: 71.34328358208955

Inputamos los datos de PM2.5 mediante el algoritmo de KNN


localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 10/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

K vecinos mas cercanos o K-NN (K Nearest Neighbours)

Sckit Learn es una libreria de Machine Learning que nos permite utilizar una serie de
algoritmos de aprendizaje automatico

In [23]: # Nos quedamos con las columnas que son solo de tipo numérico
df = df.drop(columns=['CONTAMINANTE', 'ESTACION', 'ZONA'])
df.head(5)

Out[23]:
FECHA PM10 PM25 O3 NO2 CO SO2 MAXIMO AÑO MES DIA

0 2021-01-01 160 221.0 43 25 26 5 221 2021 1 1

1 2021-02-01 143 203.0 47 23 11 5 203 2021 2 1

2 2021-03-01 116 111.0 42 22 14 5 116 2021 3 1

3 2021-04-01 111 104.0 76 28 12 5 111 2021 4 1

4 2021-05-01 115 99.0 67 29 16 5 115 2021 5 1

In [24]: # Nos quedamos con las columnas que son solo de tipo numérico
df = df.drop(columns=['FECHA'])
df.head(5)

Out[24]:
PM10 PM25 O3 NO2 CO SO2 MAXIMO AÑO MES DIA

0 160 221.0 43 25 26 5 221 2021 1 1

1 143 203.0 47 23 11 5 203 2021 2 1

2 116 111.0 42 22 14 5 116 2021 3 1

3 111 104.0 76 28 12 5 111 2021 4 1

4 115 99.0 67 29 16 5 115 2021 5 1

In [25]: # fit es la instruccion que AJUSTA los datos del modelo


from sklearn.impute import KNNImputer

imputer = KNNImputer(n_neighbors=10)
imputed = imputer.fit_transform(df)
df = pd.DataFrame(imputed, columns=df.columns)

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 11/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [26]: #Verificar renglones nulos -- Con el objetivo de comprobar si el dataframe ya no


df.isna().sum()

Out[26]: PM10 0

PM25 0

O3 0

NO2 0

CO 0

SO2 0

MAXIMO 0

AÑO 0

MES 0

DIA 0

dtype: int64

In [27]: #Se guarda el dataframe sobre un archivo de texto csv


df.to_csv('datos/contaminandepurado.csv', sep = '|', index=False)

Cargamos el dataset depurado

In [28]: #Cargar el dataset de contaminacion


datos = pd.read_csv('datos/contaminandepurado.csv', sep = '|')
#Creamos el dataframe
datos = pd.DataFrame(datos)

In [29]: datos.head()

Out[29]:
PM10 PM25 O3 NO2 CO SO2 MAXIMO AÑO MES DIA

0 160.0 221.0 43.0 25.0 26.0 5.0 221.0 2021.0 1.0 1.0

1 143.0 203.0 47.0 23.0 11.0 5.0 203.0 2021.0 2.0 1.0

2 116.0 111.0 42.0 22.0 14.0 5.0 116.0 2021.0 3.0 1.0

3 111.0 104.0 76.0 28.0 12.0 5.0 111.0 2021.0 4.0 1.0

4 115.0 99.0 67.0 29.0 16.0 5.0 115.0 2021.0 5.0 1.0

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 12/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [30]: datos['PM25'].hist()

Out[30]: <AxesSubplot:>

In [31]: #Estadistica descriptiva del dataset


datos.describe()

Out[31]:
PM10 PM25 O3 NO2 CO SO2 MAXIMO

count 4018.000000 4018.000000 4018.000000 4018.000000 4018.000000 4018.000000 4018.000000

mean 89.084868 94.470234 60.166750 28.530612 17.374316 9.078397 96.210553

std 31.311583 22.578944 22.617207 9.963248 6.306799 4.018327 27.985326

min 14.000000 54.000000 15.000000 7.000000 5.000000 3.000000 23.000000

25% 64.000000 77.500000 43.000000 21.000000 13.000000 6.000000 76.000000

50% 95.000000 93.900000 57.000000 27.000000 17.000000 8.000000 100.000000

75% 112.000000 108.000000 76.000000 34.000000 21.000000 11.000000 114.000000

max 328.000000 277.000000 136.000000 88.000000 65.000000 40.000000 328.000000

In [32]: #Mediana
datos['PM25'].median()

Out[32]: 93.9

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 13/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

PM25 es una variable continua y sus valores van desde 54 hasta 277 partes por millon
(ppm)

Generamos una variable discreta que contenga los valores de calidad


mediante la columna de PM25

In [33]: # Creamos las 5 categorías propuestas para la interpretación de la calidad del ai


pd.cut(datos['PM25'], bins = [0, 50, 100, 150, 200, 350], labels = ['BUENA', 'REG
'EXTREMADAMENTE MALA']).value_counts()

Out[33]: REGULAR 2420

MALA 1549

MUY MALA 31

EXTREMADAMENTE MALA 18

BUENA 0

Name: PM25, dtype: int64

In [34]: # Agregamos la columna calidad al data frame


# Estamos agregando una columna CATEGÓRICA al dataframe
datos['CALIDAD'] = pd.cut(datos['PM25'], bins = [0, 50, 100, 150, 200, 350], labe
'EXTREMADAMENTE MALA'])
datos.head()

Out[34]:
PM10 PM25 O3 NO2 CO SO2 MAXIMO AÑO MES DIA CALIDAD

0 160.0 221.0 43.0 25.0 26.0 5.0 221.0 2021.0 1.0 1.0 EXTREMADAMENTE MALA

1 143.0 203.0 47.0 23.0 11.0 5.0 203.0 2021.0 2.0 1.0 EXTREMADAMENTE MALA

2 116.0 111.0 42.0 22.0 14.0 5.0 116.0 2021.0 3.0 1.0 MALA

3 111.0 104.0 76.0 28.0 12.0 5.0 111.0 2021.0 4.0 1.0 MALA

4 115.0 99.0 67.0 29.0 16.0 5.0 115.0 2021.0 5.0 1.0 REGULAR

In [35]: #Dias de calidad de aire


datos['CALIDAD'].value_counts()

Out[35]: REGULAR 2420

MALA 1549

MUY MALA 31

EXTREMADAMENTE MALA 18

BUENA 0

Name: CALIDAD, dtype: int64

In [36]: ##Porcentaje de ocurrencia


datos['CALIDAD'].value_counts(normalize = True)

Out[36]: REGULAR 0.602290

MALA 0.385515

MUY MALA 0.007715

EXTREMADAMENTE MALA 0.004480

BUENA 0.000000

Name: CALIDAD, dtype: float64

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 14/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [37]: datos['CALIDAD'].hist()

Out[37]: <AxesSubplot:>

In [38]: # Vamos a generar una columna que nos indique si la calidad del aire es Regular (
# o la calidad del aire es Mala (1)
datos['CALIDAD_NUMERICA'] = pd.cut(datos['PM25'], bins = [0, 100, 350], labels =
datos.head()

Out[38]:
PM10 PM25 O3 NO2 CO SO2 MAXIMO AÑO MES DIA CALIDAD CALIDAD

EXTREMADAMENTE
0 160.0 221.0 43.0 25.0 26.0 5.0 221.0 2021.0 1.0 1.0
MALA

EXTREMADAMENTE
1 143.0 203.0 47.0 23.0 11.0 5.0 203.0 2021.0 2.0 1.0
MALA

2 116.0 111.0 42.0 22.0 14.0 5.0 116.0 2021.0 3.0 1.0 MALA

3 111.0 104.0 76.0 28.0 12.0 5.0 111.0 2021.0 4.0 1.0 MALA

4 115.0 99.0 67.0 29.0 16.0 5.0 115.0 2021.0 5.0 1.0 REGULAR

In [39]: #Libreria de gráficas y visualización


import seaborn as sns

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 15/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [40]: #Matriz de correlacion


#Correlación: El grado de asociacion entre las variables numéricas, es decir,
#que tanto explica una variable a la otra
corr = datos.corr()
corr

Out[40]:
PM10 PM25 O3 NO2 CO SO2 MAXIMO AÑO

PM10 1.000000 0.874252 0.299078 0.338456 0.301887 0.082287 0.938529 2.103737e-01

PM25 0.874252 1.000000 0.331419 0.385270 0.361460 0.151119 0.943313 1.202286e-01

-3.852494e-
O3 0.299078 0.331419 1.000000 0.284944 0.100701 0.098451 0.339216
03

-4.103547e-
NO2 0.338456 0.385270 0.284944 1.000000 0.606256 0.430323 0.292774
01

-5.064623e-
CO 0.301887 0.361460 0.100701 0.606256 1.000000 0.364660 0.252290
01

-5.007257e-
SO2 0.082287 0.151119 0.098451 0.430323 0.364660 1.000000 0.066001
01

MAXIMO 0.938529 0.943313 0.339216 0.292774 0.252290 0.066001 1.000000 2.497672e-01

AÑO 0.210374 0.120229 -0.003852 -0.410355 -0.506462 -0.500726 0.249767 1.000000e+00

-2.366958e-
MES -0.156352 -0.140472 -0.123525 -0.089038 -0.061362 -0.022786 -0.147185
14

-4.414686e-
DIA -0.046107 -0.037764 -0.033124 -0.009355 -0.027731 -0.020427 -0.037031
15

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 16/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [41]: sns.heatmap(corr, cmap="Reds", annot=True)

Out[41]: <AxesSubplot:>

Recordar que nuestra variable objetivo es el PM25 (target), es decir, la consideramos como
nuestra variable dependiente. Para nuestro objetivo se trata de predecir la calidad del aire
de las partículas PM2.5. Todas las demás variables serán las variables
independientes.

De la matriz de correlación podemos observar que el dióxido de azufre (SO2) tiene un


porcentaje de correlación muy bajo con relación a la variable dependiente (PM25), 15%,
esto quiere decir que el SO2 puede NO explicar a la variable dependiente (PM25).

El valor de la columna MAXIMO tiene un porcentaje de correlación muy alto con otra
variable independiente (PM10), esto es un riesgo para el modelo, es decir, porcentajes de
correlación muy altos entre variables independientes se tendrán que analizar porque
alguna de estas variables está de más, y podrían sobreajustar el modelo, es decir,
explicarlo de manera muy optimista o pesimista.

Análisis de regresión lineal


In [42]: #Nos quedamos con las columnas que son solo de tipo numérico y que explican nuest
#Quitamos el valor de la columna MAXIMO debido a su alta correlación con la varia
datos = datos.drop(['MAXIMO','AÑO','MES','DIA','CALIDAD','CALIDAD_NUMERICA'], axi
datos.head(5)

Out[42]:
PM10 PM25 O3 NO2 CO SO2

0 160.0 221.0 43.0 25.0 26.0 5.0

1 143.0 203.0 47.0 23.0 11.0 5.0

2 116.0 111.0 42.0 22.0 14.0 5.0

3 111.0 104.0 76.0 28.0 12.0 5.0

4 115.0 99.0 67.0 29.0 16.0 5.0

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 17/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

Objetivo: Predecir mediante Regresion Lineal el comportamiento de las particulas PM2.5 (target)
con base en los valores de las demas variavles independientes.

Target(PM2.5). Variable dependiente

Todas las demas columnas: Variables independientes

In [43]: # Definimos las 'X' y 'y'


# Variables independientes: PM10, 03, NO2, CO, SO2
#axis=1 actua sobre las columnas, axis=0 actua sobre los renglones
X = datos.drop('PM25', axis=1)
y = datos['PM25']

In [44]: #X
#y

Metodo de la exlusión

In [45]: # Dividimos el conjunto de datos en datos de entrenamiento y datos de prueba


from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_s

In [46]: #X_train
#X_test
#y_train
#y_test

In [47]: # 70% en datos de entrenamiento


X_train.shape

Out[47]: (2812, 5)

In [48]: #30% en datos de prueba


X_test.shape

Out[48]: (1206, 5)

In [49]: # Construimos el modelo de regresión lineal


from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score # Calcular el coeficiente de correlación R2
from sklearn import metrics

# Ajustamos el modelo (fit)
linreg = LinearRegression()
linreg.fit(X_train, y_train)

Out[49]: LinearRegression()

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 18/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

In [50]: print('Intercepto: ', linreg.intercept_)


print('Coeficientes: ', linreg.coef_)

Intercepto: 28.14095857998423

Coeficientes: [0.58691008 0.07191632 0.04377401 0.38804681 0.20198829]

y = 0.58691 x0 + 0.071916x1 + 0.04377x2 + 0.38804x3 + 0.201988x4 + 28.1409585

Hasta ahorita entrenamos el modelo con los datos de entrenamiento,


ahora vamos a realizar la predicción con los datos de prueba.

In [51]: # Realizamos las predicciones con los datos de prueba


y_pred = linreg.predict(X_test)

In [52]: r2_score(y_test, y_pred)

Out[52]: 0.764598758120575

Evaluación del modelo


In [53]: #Media de las particulas PM2.5
y.mean()

Out[53]: 94.4702339472375

In [54]: import numpy as np

In [55]: # Calcular el valor de R2, MAE, MSE, RMSE en los datos de prueba
print('Valor de R2', r2_score(y_test, y_pred))
print('\n')
print('MAE: ', metrics.mean_absolute_error(y_test, y_pred))
print('\n')
print('MSE: ', metrics.mean_squared_error(y_test, y_pred))
print('\n')
print('RMSE: ', np.sqrt(metrics.mean_squared_error(y_test, y_pred)))

Valor de R2 0.764598758120575

MAE: 7.3663553371845705

MSE: 114.36631544290967

RMSE: 10.694218786003477

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 19/20
8/6/22, 10:42 contaminazmvt - Jupyter Notebook

La interpretación de los resultados es la siguiente: Con una certeza del


76.4% los valores de PM 2.5 estarán entre 94.47 ppm mas menos 7.36
(MAE) ppm, es decir, 87.11 y 101.83. Esto es la calidad de aire por
particulas PM2.5 en el Valle de Toluca seguirá en los rangos de regular
hasta mala.

localhost:8888/notebooks/Documents/ECATSIGCD/contaminazmvt.ipynb 20/20

También podría gustarte