Regresión lineal multiple

Hipotesis: Se tiene una base de datos con 24 vehiculos de diferentes marcas, cada vehiculo cuenta con su potencia, consumo, peso, cilindraje y modelo, a el consecionario que vende estos vehiculos le han llegado multiples quejas de clientes alegando que el consumo de sus vehiculos no es adecuado para el cilindraje y la potencia de esos mismos; el consecionario afirma que el consumo de sus vehiculos es proporcional a su cilindraje y potencia.

1). Importar los siguientes módulos o paquetes:

In [ ]:
import pandas as pd                                # Se trabaja todo lo que es la estructura de los datos
    import statsmodels.formula.api as smf              # Permite ajustar modelos estadísticos utilizando fórmulas de estilo R
    import numpy as np                                 # representa matrices multidimensionales, equivalentes a las matrices del R
    from matplotlib import pyplot                      # Permite la generación de gráficos
    from mpl_toolkits.mplot3d import Axes3D            # Permite agregar eje tridimensionales
    from sklearn.linear_model import LinearRegression  # sklearn es una libreria que cuenta con algoritmos de clasificación, regresión, clustering y reducción de dimensionalidad
    from sklearn import metrics                        # sklearn es una libreria que cuenta con algoritmos de clasificación, regresión, clustering y reducción de dimensionalidad
    

2). Leer la base de datos:

In [ ]:
from google.colab import files
    
    uploaded = files.upload()   # Importamos los datos dentro del colab
    
Upload widget is only available when the cell has been executed in the current browser session. Please rerun this cell to enable.
Saving cars.csv to cars.csv
    

3). Estructura y primeras observaciones de la base de datos:

In [ ]:
df = pd.read_csv('cars.csv')    # Lo convertimos en un DataFrame
    

La base de datos utilizada almacena las caracteristicas de un vehiculo siendo estas el modelo, cilindraje, potencia, peso y consumo, teniendo el cuenta el tamaño de la muestra de los datos nos decantaremos por usar el test de shapiro, pero antes ejecutaremos un analisis grafico para determinar si vale la pena implementar un test numerico.

In [ ]:
df    # Observamos el DataSet
    
Out[ ]:
modelo cilindraje potencia peso consumo
0 Maserati 2789 209 1485 14.5
1 Daihatsu 846 32 650 5.7
2 Toyota 1331 55 1010 7.1
3 Fort 1390 54 1110 8.6
4 Mazda 2497 122 1330 10.8
5 Volvo 2473 125 1570 12.7
6 Toyota 2438 97 1800 12.8
7 Renault 2165 101 1500 11.7
8 Honda 1396 66 1140 7.7
9 VW 1984 85 1155 9.5
10 Suzuki 993 39 790 5.8
11 Lancia 2958 150 1550 11.9
12 Mercedes 5987 300 2250 18.7
13 Volvo 2435 106 1370 10.8
14 VW 1390 44 955 6.5
15 Hyundai 2972 107 1400 11.7
16 Opel 1195 33 895 6.8
17 Opel 1597 74 1080 7.4
18 Peugeot 1761 74 1100 9.0
19 Mitsubishi 1998 66 1300 7.6
20 Citroen 1998 89 1140 8.8
21 Peugeot 1998 89 1560 10.8
22 Fiat 899 29 730 6.1
23 Seat 1984 85 1635 11.6
24 Ford 1242 55 940 6.6
In [ ]:
df.describe()   # Observamos su estructura
    
Out[ ]:
cilindraje potencia peso consumo
count 25.000000 25.000000 25.000000 25.000000
mean 2028.640000 91.440000 1257.800000 9.648000
std 1036.760776 59.611995 365.957876 3.149751
min 846.000000 29.000000 650.000000 5.700000
25% 1390.000000 55.000000 1010.000000 7.100000
50% 1984.000000 85.000000 1155.000000 9.000000
75% 2438.000000 106.000000 1500.000000 11.700000
max 5987.000000 300.000000 2250.000000 18.700000

4). Diagrama de dispersión y test grafico.

In [ ]:
fig = pyplot.figure(figsize=(8, 6))          # Ajustes del gráfico
    ax = Axes3D(fig)
    
    x1 = df['cilindraje']                        # Variable exogena
    x2 = df['potencia']                          # Datos eje Y
    y = df['consumo']                            # Datos eje Z (Var. Respuesta)
    
    ax.scatter(x1, x2, y, marker='*', c='r')
    ax.set_xlabel('Cilindraje del vehiculo')     # Etiqueta del eje X1
    ax.set_ylabel('Potencia del vehiculo')       # Etiqueta del eje X2
    ax.set_zlabel('Consumo del vehiculo')        # Etiqueta del eje Y
    
Out[ ]:
Text(0.5, 0, 'Consumo del vehiculo')
No description has been provided for this image

5). Correlacion entre variables

In [ ]:
df.corr()   # Podemos observar un alto indice de correlacion entre cada variable
    
Out[ ]:
cilindraje potencia peso consumo
cilindraje 1.000000 0.947032 0.874818 0.915156
potencia 0.947032 1.000000 0.827966 0.925451
peso 0.874818 0.827966 1.000000 0.942124
consumo 0.915156 0.925451 0.942124 1.000000

6). Generamos el Ordinary Least Square o el modelo

In [ ]:
reg = smf.ols('consumo ~ cilindraje + potencia',data=df)   # Se establece la regrecion con el Ordinary Least Square dictando que el consumo
    res = reg.fit()                                            # va a ser aproximandamente igual a la suma del cilindraje y potencia.
    
In [ ]:
print(res.summary())    # Imprimimos los resultados
    print(res.rsquared)
    print(res.params)
    
                            OLS Regression Results                            
    ==============================================================================
    Dep. Variable:                consumo   R-squared:                       0.871
    Model:                            OLS   Adj. R-squared:                  0.859
    Method:                 Least Squares   F-statistic:                     74.27
    Date:                Tue, 15 Nov 2022   Prob (F-statistic):           1.65e-10
    Time:                        22:58:46   Log-Likelihood:                -38.047
    No. Observations:                  25   AIC:                             82.09
    Df Residuals:                      22   BIC:                             85.75
    Df Model:                           2                                         
    Covariance Type:            nonrobust                                         
    ==============================================================================
                     coef    std err          t      P>|t|      [0.025      0.975]
    ------------------------------------------------------------------------------
    Intercept      4.5806      0.580      7.902      0.000       3.378       5.783
    cilindraje     0.0011      0.001      1.575      0.130      -0.000       0.003
    potencia       0.0301      0.013      2.390      0.026       0.004       0.056
    ==============================================================================
    Omnibus:                        2.471   Durbin-Watson:                   1.801
    Prob(Omnibus):                  0.291   Jarque-Bera (JB):                2.083
    Skew:                           0.675   Prob(JB):                        0.353
    Kurtosis:                       2.581   Cond. No.                     5.57e+03
    ==============================================================================
    
    Notes:
    [1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
    [2] The condition number is large, 5.57e+03. This might indicate that there are
    strong multicollinearity or other numerical problems.
    0.8710005573273458
    Intercept     4.580597
    cilindraje    0.001141
    potencia      0.030110
    dtype: float64
    

7). Ecuacion y prediccion

In [ ]:
lm = LinearRegression()
    X = df[['cilindraje','potencia']]
    lm.fit(X,y)
    prediccion = lm.predict(X)
    a = lm.intercept_
    b = lm.coef_
    
In [ ]:
print('Prediccion')
    print('*'*100)
    print(prediccion)     # Valores segun la prediccion
    print('*'*100)
    print(y)              # Valores actuales del consumo
    print(lm.score(X,y))  # Retornamos el coeficiente de determinacion en la prediccion
    
Prediccion
    ****************************************************************************************************
    [14.05509024  6.50918153  7.75496871  7.79216271 11.10243572 11.16538745
     10.28238546 10.09140198  8.16032544  9.40316975  6.88763979 12.47139434
     20.44318411 10.54995194  7.49106414 11.19264093  6.93741079  8.63049369
      8.81757558  8.84705289  9.53957958  9.53957958  6.47931136  9.40316975
      7.65344256]
    ****************************************************************************************************
    0     14.5
    1      5.7
    2      7.1
    3      8.6
    4     10.8
    5     12.7
    6     12.8
    7     11.7
    8      7.7
    9      9.5
    10     5.8
    11    11.9
    12    18.7
    13    10.8
    14     6.5
    15    11.7
    16     6.8
    17     7.4
    18     9.0
    19     7.6
    20     8.8
    21    10.8
    22     6.1
    23    11.6
    24     6.6
    Name: consumo, dtype: float64
    0.8710005573273458
    

8). Comparativas y Error estandar

In [ ]:
resultados ={'Real':df['consumo'],'Prediccion':prediccion}
    result = pd.DataFrame(data=resultados)
    print(result)
    
    Real  Prediccion
    0   14.5   14.055090
    1    5.7    6.509182
    2    7.1    7.754969
    3    8.6    7.792163
    4   10.8   11.102436
    5   12.7   11.165387
    6   12.8   10.282385
    7   11.7   10.091402
    8    7.7    8.160325
    9    9.5    9.403170
    10   5.8    6.887640
    11  11.9   12.471394
    12  18.7   20.443184
    13  10.8   10.549952
    14   6.5    7.491064
    15  11.7   11.192641
    16   6.8    6.937411
    17   7.4    8.630494
    18   9.0    8.817576
    19   7.6    8.847053
    20   8.8    9.539580
    21  10.8    9.539580
    22   6.1    6.479311
    23  11.6    9.403170
    24   6.6    7.653443
    
In [ ]:
ECM = metrics.mean_squared_error(df['consumo'],prediccion)
    print(ECM)         # Error estandar
    r_cuadrado = metrics.r2_score(df['consumo'],prediccion)
    print(r_cuadrado)  # R cuandrado o coeficiente de determinacion
    
1.2286030759608555
    0.8710005573273458
    

9). Graficasion de la prediccion

In [ ]:
fig = pyplot.figure(figsize=(8, 6))               # Ajustes del gráfico
    ax = Axes3D(fig)
    
    x1 = df['cilindraje']                             # Variable exogena
    x2 = df['potencia']                               # Datos eje Y
    y = df['consumo']                                 # Datos eje Z (Var. Respuesta)
    
    ax.scatter(x1, x2, y, marker='*', c='r')          # Datos actuales
    ax.scatter(x1, x2, prediccion, marker='+', c='b') # Datos segun la prediccion
    ax.set_xlabel('Cilindraje del vehiculo')          # Etiqueta del eje X1
    ax.set_ylabel('Potencia del vehiculo')            # Etiqueta del eje X2
    ax.set_zlabel('Consumo del vehiculo')             # Etiqueta del eje Y
    
Out[ ]:
Text(0.5, 0, 'Consumo del vehiculo')
No description has been provided for this image

Conclusiones

Podemos observar que como existe una estrecha correlacion entre cada valor de la base de datos, el modelo predictivo indica un constante crecimiento del consumo de cada vehiculo en funcion de su cilindraje y potencia descartando la hipotesis alternativa presentada por los clientes del concesionario sugiriendo que el consumo no era el adecuado para sus vehiculos.

Error Tipo 1: Se hace caso a las quejas de los clientes y se detiene el proceso de importacion y exportacion de vehiculos generando perdidas en el negocio tratando de encotrar defectos en los vehiculos comprados a los dristribuidores.

Error Tipo 2: Se les comenta a los clientes que no hay defecto alguno en los vehiculos vendidos y se genera desconfianza en los productos del concesionario debido a la mala calidad de sus vehiculos.