Fundamentos de estadística y probabilidad para Data Science

4.1 Regresión lineal simple: Introducción

Conceptos básicos sobre relación entre variables

Ejemplo de relación entre dos variables

Vamos a estudiar la relación entre variables a nivel gráfico de los datasets TOP TRUMPS:

Se necesita realizar un escalado para poder comparar las distribuciones.

Boxplot

Code
lotr %>%
  select(tamano, fuerza) %>%
  sapply(scale) %>% 
  as.data.frame() %>% 
  pivot_longer(cols = everything(), names_to = "variable", values_to = "valor") %>%
  ggplot(aes(x = variable, y = valor, color = variable)) +
    geom_boxplot() +
    labs(
      title = "LOTR: Fuerza vs Tamaño",
      x = "Variable",
      y = "Valor",
      color = "Variable"
    ) +
    theme_bw()

Densidad

Code
lotr %>%
  select_if(is.numeric) %>%
  sapply(scale) %>%
  as.data.frame() %>%
  ggplot() +
  geom_density(aes(x = fuerza, color = "Fuerza")) +
  geom_density(aes(x = tamano, color = "Tamaño")) +
  labs(
    title = "Función de densidad comparativa con variables escaladas",
    x = "Valor (z-score)",
    y = "Densidad",
    color = "Variable"
  ) +
  scale_color_manual(
    values = c("Fuerza" = "red",
               "Tamaño" = "blue")
  ) +
  theme_classic()

Diagrama de dispersión:

Code
lotr %>%
  ggplot() +
  geom_point(aes(x = tamano, y = fuerza)) +
  labs(
    title = "Fuerza vs Tamaño",
    x = "Tamaño",
    y = "Fuerza"
  ) +
  geom_smooth(aes(x = tamano, y = fuerza)) +
  geom_text_repel(aes(x = tamano, y = fuerza, label = nombre), size = 3, vjust = -1) +
  theme_bw()

Si eliminamos el anillo:

Code
lotr_sin_anillo <- lotr %>%
  filter(nombre != "EL_ANILLO_UNICO")
Code
lotr_sin_anillo %>%
  ggplot() +
  geom_point(aes(x = tamano, y = fuerza)) +
  labs(
    title = "Fuerza vs Tamaño",
    x = "Tamaño",
    y = "Fuerza"
  ) +
  geom_smooth(aes(x = tamano, y = fuerza)) +
  geom_text_repel(aes(x = tamano, y = fuerza, label = nombre), size = 3, vjust = -1) +
  theme_bw()

Code
 lqsa %>%
  ggplot(aes(x = Locura, y = Convivencia)) +
  geom_point() +
  labs(
    title = "LQSA: relación entre Locura y Convivencia",
    x = "Locura",
    y = "Convivencia"
  ) +
  geom_smooth() +
  geom_text_repel(aes(label = Nombre), size = 3, vjust = -1) +
  theme_bw()

Covarianza Y Correlación

Covarianza

Para una muestra de n datos bivariantes \((x_{1}, y_{1}), ..., (x_{n}, y_{n})\) la covarianza entre dos variables (x, y) es:

\(s_{xy}=\displaystyle {\frac{{\sum_{i=1}^{n}\left(x_{i}-\overline{x}\right)} \left(y_{i}-\overline{y}\right)}{n-1}}\), donde \(\overline{x}\) e \(\overline{y}\) son las medias de ambas variables.

Es una medida de la fuerza de la relación entre dos variables cuantitativas. Si la covarianza es positiva, existe una relación creciente entre x e y, si es negativa, la relación será decreciente.

Ejemplo: Relación entre tamaño y fuerza en LOTR (TOP TRUMPS)

Cálculo de la covarianza (con y sin el anillo):

sum(((lotr$tamano - mean(lotr$tamano)) * (lotr$fuerza - mean(lotr$fuerza)))/(nrow(lotr)-1))
[1] 32.25862
sum(((lotr_sin_anillo$tamano - mean(lotr_sin_anillo$tamano)) * (lotr_sin_anillo$fuerza - mean(lotr_sin_anillo$fuerza)))/(nrow(lotr_sin_anillo)-1))
[1] 41.3202
cov(lotr$tamano, lotr$fuerza)
[1] 32.25862
cov(lotr_sin_anillo$tamano, lotr_sin_anillo$fuerza)
[1] 41.3202

Ejemplo: Covarianza negativa en la relación entre Locura y Convivencia en LQSA (TOP TRUMPS)

cov(lqsa$Locura, lqsa$Convivencia)
[1] -100.3379

En la covarianza, el signo es lo importante y no el valor numérico. Los datos vendrán con diferentes unidades y tendrán diferente significado, solo mide en qué dirección varían los datos.

Correlación

El cálculo de correlación más conocido es coeficiente de correlación de Pearson, aplicado a dos variables cuantitativas y mide la dependencia lineal entre ellas.

Como la varianza solo informa de la dirección en la que varían los datos, dividiendo la covarianza por el producto la desviación estándar de x e y, obtenemos un coeficiente de correlación que varía entre -1 y 1, siendo -1 y 1 una relación lineal perfecta entre ambas variables.

Matemáticamente:

\(r_{xy}=\displaystyle{\frac{s_{xy}}{s_{x}s_{y}}}\)

Valores próximos a cero indican que ambas variables son independientes, mientras que valores próximos a 1 indican que si la variable x aumenta y lo hará también y de una forma lineal (la relación funcional que liga y y xi es aproximadamente una recta). Si el valor del coeficiente fuese próximo a -1, aumentos de la variable xi irían aparejados de descensos (lineales) de la variable respuesta y.

cov(lotr$fuerza, lotr$tamano)/(sd(lotr$tamano)*sd(lotr$fuerza))
[1] 0.5405759

Aplicando la función cor:

cor(lotr$tamano, lotr$fuerza)
[1] 0.5405759
cor(lotr_sin_anillo$tamano, lotr_sin_anillo$fuerza)
[1] 0.7867558
cor(lqsa$Locura, lqsa$Convivencia)
[1] -0.5365953

Ejemplo: Relación entre magia y miedo LOTR

Code
 lotr %>%
  ggplot(aes(x = magia, y = miedo)) +
  geom_point() +
  labs(
    title = "Relación no lineal entre magia y miedo",
    x = "Magia",
    y = "Miedo"
  ) +
  geom_smooth() +
  geom_text_repel(aes(label = nombre), size = 3, vjust = -1) +
  theme_bw()

cor(lotr$magia, lotr$miedo)
[1] 0.2744178

Matriz de correlación

Realizar el cálculo de correlación entre todas las variables de un data frame, podría ser algo tedioso. Afortunadamente, podemos calcular y visualizar la matriz de correlación mediante funciones que R tiene para ello.

lotr_sin_anillo %>%
  select_if(is.numeric) %>%
  filter(tamano > 1) %>%
  cor()
             tamano    fuerza   valentia      magia      miedo
tamano    1.0000000 0.7867558 -0.2021155  0.3862160  0.8584300
fuerza    0.7867558 1.0000000  0.0781738  0.0848125  0.6971454
valentia -0.2021155 0.0781738  1.0000000 -0.1716607 -0.3318364
magia     0.3862160 0.0848125 -0.1716607  1.0000000  0.2305015
miedo     0.8584300 0.6971454 -0.3318364  0.2305015  1.0000000
lotr_sin_anillo %>%
  select_if(is.numeric) %>%
  cor() %>%
  corrplot(method = "circle")

lqsa %>%
  select_if(is.numeric) %>%
  cor() %>%
  corrplot(method= "square", type = "lower")

harry_potter %>%
  select_if(is.numeric) %>%
  cor() %>%
  corrplot(method = "color")

Conceptos básicos sobre regresión

Antes de introducirnos en el concepto de regresión, veamos algunos de los tipos de problemas que se abordan mediante algoritmos de aprendizaje automático:

Los dos tipos principales de problemas que se aboradaran durante el curso son de regresión y de clasificación.

  • Problemas de Regresión: Los problemas de regresión buscan predecir valores continuos. Esto significa que estamos interesados en averiguar cuánto o cuántos. Por ejemplo:
    • Predicción de precios: ¿Cuál será el precio de venta de una casa dadas sus características como tamaño, ubicación y número de habitaciones?
    • Estimaciones de tiempo: ¿Cuánto tiempo tomará completar una tarea dada la complejidad y los recursos disponibles?
    • Pronóstico de ventas: ¿Cuántas unidades de un producto se venderán el próximo mes?
    • Predicciones de demanda: ¿Cuánta energía se consumirá hoy?
  • Problemas de Clasificación: Los problemas de clasificación, por otro lado, implican asignar categorías a los datos. Estamos interesados en saber qué o cuál categoría. Por ejemplo:
    • Diagnóstico médico: ¿Es maligno o benigno un tumor basado en las características de las células?
    • Reconocimiento de imágenes: ¿Es la imagen de un perro, un gato o un pájaro? Sistemas de reconocimiento facial.
    • Aprobación de crédito: ¿Debería aprobarse o denegarse una solicitud de crédito basada en el historial financiero del solicitante?
    • Fuga de clientes o empleados (churn): ¿se va a marchar a la competencia?
  • Otro tipo de problemas:
    • Clustering: Tratar de crear grupos agrupando datos sin etiquetar en función de determinadas características.
    • Reducción de la dimensionalidad: Reducir el número de variables perdiendo la mínima información posible.
    • Sistemas de recomendación: Sugerir productos al usuario en función de sus intereses y comportamientos anteriores así como el comportamiento de otros usuarios
    • Detección de anomalías: Identificar casos raros o inusuales, prevención de averías
    • Optimización y toma de decisiones secuenciales: Maximizar recompensa a largo plazo interactuando con el entorno. Juegos, robotica, publicidad en línea, procesos industriales, etc.

Regresión

La regresión es una herramienta estadística que nos permite explorar y establecer la relación entre dos o más variables. Hemos de pensar en una variable como una característica que puede cambiar y que podemos medir. Por ejemplo, la relación entre las horas de estudio y las calificaciones de un examen, o entre la temperatura y el consumo energético. Hay diferentes tipos de regresión:

  • Regresión lineal: Cuando la relación entre las variables es lineal. Cuando solamente hay una variable predictora, se trata de una línea recta.
  • Regresión Logística: Utilizada cuando la variable que queremos predecir es categórica, como sí/no.
  • Regresión Polinomial: Cuando la relación no es una línea recta, sino más curvada o compleja.

La regresión lineal es importante porque es el punto de partida para entender cómo las variables se relacionan entre sí de una manera simple y directa. Nos permite predecir el valor de una variable basándonos en el valor de otra.

Modelo

Un modelo es una ecuación o función matemática que describe la relación entre las variables. En ciencia de datos, construimos modelos para predecir o explicar fenómenos.

Tipos de variables

  • Variable Objetivo: Es la variable que pretende estimar mediante un modelo. Se denomina también: variable de respuesta, variable dependiente.
  • Variables predictoras: Puede ser una (regresión simple) o varias. Contiene la información con la que el modelo elaborará la predicción. Se denomina también: variable explicativa, variable independiente

La elaboración del modelo, nos permite realizar predicciones sobre los valores de la variable de respuesta.

La variable de respuesta y la predictora, pueden ser completamente intercambiables, dependiendo del análisis que se quiera realizar o los datos que se tienen y sobre qué valor se quieren hacer las predicciones.

Modelo de Regresión lineal simple

Ahora, vamos a enfocarnos en el modelo de regresión lineal simple. Este modelo solo considera dos variables: una independiente y una dependiente. La variable independiente es la causa presumida, mientras que la variable dependiente es el efecto.

La relación entre estas dos variables se representa con la siguiente ecuación:

  • \(Y = a + bX\)

  • Y es la variable dependiente que queremos predecir.

  • X es la variable independiente que usamos para hacer la predicción.

  • a es la intersección con el eje Y (ordenada en el origen), también conocida como el término de intercepción, que representa el valor esperado de Y cuando X es 0.

  • b es la pendiente, que indica cuánto cambia Y en promedio cuando X cambia en una unidad.

El objetivo es encontrar los valores de a y b que mejor se ajusten a nuestros datos. Esto se hace a través de un proceso llamado “mínimos cuadrados”, que minimiza la suma de los cuadrados de las diferencias entre los valores observados y los predichos por el modelo.

En términos más simples, la regresión lineal simple nos ayuda a responder preguntas como “¿Si aumento mis horas de estudio, cuánto puedo esperar que mejoren mis calificaciones?”, y es una herramienta fundamental para predecir y tomar decisiones basadas en datos.

¿Cómo se obtiene el modelo analíticamente: enccontrar los valores a y b?

  • \(b = \frac{\sum_{i=1}^{n} (x_i - \overline{x})(y_i - \overline{y})}{\sum_{i=1}^{n} (x_i - \overline{x})^2}\)

  • \(b = \frac{\text{Cov}(x, y)}{\text{Var}(x)}\)

  • \(a =\overline{y} - b\overline{x}\)

Ejemplo: Regresión lineal fuerza vs tamaño (Excluyendo el anillo):

b <- sum((lotr_sin_anillo$tamano - mean(lotr_sin_anillo$tamano)) * 
  (lotr_sin_anillo$fuerza - mean(lotr_sin_anillo$fuerza))
) / 
  sum((lotr_sin_anillo$tamano - mean(lotr_sin_anillo$tamano))**2)
b
[1] 9.258278

\(b = \frac{\text{Cov}(x, y)}{\text{Var}(x)}\)

b <- cov(lotr_sin_anillo$tamano, lotr_sin_anillo$fuerza) /
  var(lotr_sin_anillo$tamano)
b
[1] 9.258278
a <- mean(lotr_sin_anillo$fuerza) - b * mean(lotr_sin_anillo$tamano)
a
[1] -3.092715

¿Cómo se obtiene el modelo en R?

modelo_f_tam <- lm(fuerza ~ tamano, data = lotr_sin_anillo)
modelo_f_tam

Call:
lm(formula = fuerza ~ tamano, data = lotr_sin_anillo)

Coefficients:
(Intercept)       tamano  
     -3.093        9.258  
Code
lotr_sin_anillo %>%
  mutate(pred_fuerza = predict(modelo_f_tam, newdata = lotr_sin_anillo)) %>%
  ggplot(aes(x = tamano, y = fuerza)) +
  geom_point(aes(x = tamano, y = fuerza), size = 3, width = 0.2) +
  labs(
    title = "Fuerza vs Tamaño",
    x = "Tamaño",
    y = "Fuerza"
  ) +
  geom_line(aes(x = tamano, y = pred_fuerza), color = "blue", size = 1) +
  geom_segment(aes(xend = tamano, yend = pred_fuerza), color = "red", linetype = "dashed", size = 1, alpha = 0.5) +
  theme_bw()

Otro ejemplo: relación entre convivencia y locura:

modelo_conv_loc <- lm(Convivencia ~ Locura, data = lqsa)
modelo_conv_loc

Call:
lm(formula = Convivencia ~ Locura, data = lqsa)

Coefficients:
(Intercept)       Locura  
    16.9515      -0.1096  
Code
lqsa %>%
  mutate(pred_convivencia = predict(modelo_conv_loc, newdata = lqsa)) %>%
  ggplot(aes(x = Locura, y = Convivencia)) +
  geom_point(aes(x = Locura, y = Convivencia), size = 2) +
  labs(
    title = "Convivencia vs Locura",
    x = "Locura",
    y = "Convivencia"
  ) +
  geom_line(aes(x = Locura, y = pred_convivencia), color = "blue", size = 1) +
  geom_segment(aes(xend = Locura, yend = pred_convivencia), color = "red", linetype = "dashed", size = 1, alpha = 0.5) +
  theme_bw()

Ejemplo con datos “reales”: Precio del seguro en función del número de partes

Code
modelo_seg <- lm(total_payment_sek ~ n_claims, data = swedish_motor_insurance)
modelo_seg

Call:
lm(formula = total_payment_sek ~ n_claims, data = swedish_motor_insurance)

Coefficients:
(Intercept)     n_claims  
     19.994        3.414  
Code
swedish_motor_insurance %>%
  mutate(pred_total_payment_sek = predict(modelo_seg, newdata = swedish_motor_insurance)) %>%
  ggplot(aes(x = n_claims, y = total_payment_sek)) +
  geom_point(aes(x = n_claims, y = total_payment_sek), size = 2) +
  labs(
    title = "Precio del seguro vs partes",
    x = "Nº de partes",
    y = "Precio póliza"
  ) +
  geom_line(aes(x = n_claims, y = pred_total_payment_sek), color = "blue", size = 1) +
  geom_segment(aes(xend = n_claims, yend = pred_total_payment_sek), color = "red", linetype = "dashed", size = 1, alpha = 0.5) +
  theme_bw()

Modelando con predictores categóricos

Cuando trabajamos con un modelo de regresión simple y nuestra variable predictora es categórica, debemos manejar las categorías de una forma especial. Una variable categórica es aquella que puede tomar un número limitado de valores distintos y a menudo nominales, como sí/no, color de ojos, marca de coche, etc.

Para incluir una variable categórica en un modelo de regresión lineal, utilizamos lo que se llama codificación dummy o one-hot encoding. Esto implica crear una nueva variable dummy (ficticia) para cada categoría de la variable categórica, excepto una que será nuestra categoría de referencia. Estas variables dummy toman el valor de 1 si la observación pertenece a esa categoría, y 0 si no.

Por ejemplo, si tenemos una variable categórica que representa el color de un coche, que puede ser rojo, azul o verde, crearíamos dos variables dummy: una para rojo y otra para azul (si elegimos verde como nuestra categoría de referencia). La categoría de referencia no necesita una variable dummy ya que su efecto está implícito en el término de intersección del modelo.

La ecuación de un modelo de regresión lineal con una variable predictora categórica quedaría así:

\(Y = a + b_1 D_1 + b_2 D_2 + \ldots + b_k D_k + \epsilon\) donde:

  • Y es la variable objetivo.
  • a es la ordenada al origen, que también representa el valor medio de para la categoría de referencia.
  • \(b_1, b_2, \ldots, b_k\) son los coeficientes para cada una de las variables dummy $ D_1, D_2, , D_k$.
  • \(\epsilon\) es el término de error, que captura la variabilidad no explicada por el modelo.

Cada coeficiente \(b_i\) nos dice cuánto se espera que cambie \(Y\) al cambiar de la categoría de referencia a la categoría \(i\).

Ejemplo clásico de datascience: iris

Code
summary(iris)
  Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
 Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100  
 1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300  
 Median :5.800   Median :3.000   Median :4.350   Median :1.300  
 Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199  
 3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800  
 Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500  
       Species  
 setosa    :50  
 versicolor:50  
 virginica :50  
                
                
                
Code
model_ptl_vs_sp <- lm(formula = Petal.Length ~ Species, data = iris)
 model_ptl_vs_sp 

Call:
lm(formula = Petal.Length ~ Species, data = iris)

Coefficients:
      (Intercept)  Speciesversicolor   Speciesvirginica  
            1.462              2.798              4.090  

Setosa es la categoría de referencia

Code
 # Añadir + 0, modifica el nombre del coeficiente, pero no cambia el modelo
model_dummy_1_variable_cat <- lm(Petal.Length ~ Species + 0, data = iris)
model_dummy_1_variable_cat

Call:
lm(formula = Petal.Length ~ Species + 0, data = iris)

Coefficients:
    Speciessetosa  Speciesversicolor   Speciesvirginica  
            1.462              4.260              5.552  
Code
# Crear un nuevo data frame con las predicciones
predicciones <- data.frame(Species = unique(iris$Species),
                           Predicted = predict(model_ptl_vs_sp, newdata = data.frame(Species = unique(iris$Species))))

# Datos originales y las predicciones
ggplot(iris, aes(x = Species, y = Petal.Length)) +
  geom_jitter(width = 0.2, alpha = 0.5) +  # Usamos geom_jitter para evitar superposiciones
  geom_point(data = predicciones, aes(x = Species, y = Predicted), color = "red", size = 4, shape = "square") +
  labs(title = "Predicción del Tamaño del Pétalo por Especie", x = "Especie", y = "Largo del Pétalo") +
  theme_bw()

En el sentido del nº de variables es un modelo simple, pero teniendo en cuenta la transformación, al tener dos variables dummy una vez transformadas, ya no es un modelo simple.

Code
set.seed(12)
dummy_iris <- iris %>%
  select(Species, Petal.Length) %>%
  mutate(versicolor = (Species == "versicolor")*1,
         virginica = (Species == "virginica")*1) 
dummy_iris %>%
 sample_n(30, replace = FALSE) 
      Species Petal.Length versicolor virginica
1  versicolor          4.0          1         0
2  versicolor          3.5          1         0
3  versicolor          4.4          1         0
4  versicolor          4.5          1         0
5      setosa          1.4          0         0
6   virginica          6.1          0         1
7   virginica          5.2          0         1
8  versicolor          3.7          1         0
9   virginica          5.7          0         1
10  virginica          5.7          0         1
11     setosa          1.4          0         0
12  virginica          6.3          0         1
13  virginica          6.6          0         1
14     setosa          1.4          0         0
15 versicolor          4.7          1         0
16 versicolor          4.0          1         0
17  virginica          4.8          0         1
18  virginica          4.9          0         1
19  virginica          5.9          0         1
20     setosa          1.6          0         0
21  virginica          5.6          0         1
22  virginica          5.2          0         1
23     setosa          1.3          0         0
24 versicolor          5.0          1         0
25 versicolor          4.8          1         0
26     setosa          1.6          0         0
27     setosa          1.5          0         0
28 versicolor          5.1          1         0
29     setosa          1.5          0         0
30 versicolor          4.7          1         0
Code
model_dummy <- lm(Petal.Length ~ versicolor+virginica, data = dummy_iris)
model_dummy

Call:
lm(formula = Petal.Length ~ versicolor + virginica, data = dummy_iris)

Coefficients:
(Intercept)   versicolor    virginica  
      1.462        2.798        4.090  

Al tratarse de un modelo con “dos variables predictoras”, la representación gráfica quedaría en 3D:

Code
library(plotly)

# Ajustamos el modelo de regresión lineal con las variables dummy
modelo_dummy <- lm(Petal.Length ~ versicolor + virginica, data = dummy_iris)

# Creamos una malla de valores para las variables predictoras
grid <- expand.grid(versicolor = seq(0, 1, length.out = 10),
                    virginica = seq(0, 1, length.out = 10))

# Calculamos las predicciones en la malla de valores
grid$Predicted <- predict(modelo_dummy, newdata = grid)

# Creamos el gráfico 3D
plot_ly() %>%
  add_trace(data = dummy_iris, x = ~versicolor, y = ~virginica, z = ~Petal.Length, type = 'scatter3d', mode = 'markers', marker = list(size = 2)) %>%
  add_trace(data = grid, x = ~versicolor, y = ~virginica, z = ~Predicted, type = 'mesh3d') %>%
  layout(scene = list(xaxis = list(title = 'Versicolor'),
                      yaxis = list(title = 'Virginica'),
                      zaxis = list(title = 'Petal Length')))

Error común en variables dummies:

  • Crear una variable con one-hot-encoding para todas las categorías
Code
dummy_iris_error <- iris %>%
  select(Species, Petal.Length) %>%
  mutate(versicolor = (Species == "versicolor")*1,
         virginica = (Species == "virginica")*1,
         setosa = (Species == "setosa")*1)  # Información redundante
dummy_iris_error %>%
 sample_n(30, replace = FALSE) 
      Species Petal.Length versicolor virginica setosa
1      setosa          1.7          0         0      1
2  versicolor          5.1          1         0      0
3      setosa          1.5          0         0      1
4   virginica          5.6          0         1      0
5   virginica          5.3          0         1      0
6  versicolor          4.4          1         0      0
7      setosa          1.4          0         0      1
8  versicolor          4.8          1         0      0
9      setosa          1.6          0         0      1
10 versicolor          4.8          1         0      0
11  virginica          5.4          0         1      0
12  virginica          5.6          0         1      0
13  virginica          5.6          0         1      0
14 versicolor          4.5          1         0      0
15 versicolor          3.3          1         0      0
16     setosa          1.4          0         0      1
17 versicolor          4.4          1         0      0
18     setosa          1.3          0         0      1
19     setosa          1.5          0         0      1
20     setosa          1.5          0         0      1
21     setosa          1.2          0         0      1
22  virginica          4.8          0         1      0
23     setosa          1.4          0         0      1
24     setosa          1.1          0         0      1
25 versicolor          3.5          1         0      0
26 versicolor          4.7          1         0      0
27 versicolor          4.4          1         0      0
28     setosa          1.6          0         0      1
29     setosa          1.3          0         0      1
30  virginica          6.1          0         1      0
Code
model_dummy_error <- lm(Petal.Length ~ versicolor+virginica+setosa, data = dummy_iris_error)
model_dummy_error

Call:
lm(formula = Petal.Length ~ versicolor + virginica + setosa, 
    data = dummy_iris_error)

Coefficients:
(Intercept)   versicolor    virginica       setosa  
      1.462        2.798        4.090           NA  
  • Obviar la ordenada en el origen (Intercept), si añades +0 en el modelo
Code
model_dummy_error <- lm(Petal.Length ~ versicolor+virginica+0, data = dummy_iris_error)
model_dummy_error

Call:
lm(formula = Petal.Length ~ versicolor + virginica + 0, data = dummy_iris_error)

Coefficients:
versicolor   virginica  
     4.260       5.552