Autor: Fernando

  • Eigenvectors y eigenvalues

    Verás que, aunque una transformación lineal cambia la dirección de la mayoría de los vectores, existen algunos vectores especiales que no rotan, solo se estiran o encogen.
    Esos vectores son los autovectores (eigenvector), y la cantidad por la que se estiran o encogen se llama autovalor (eigenvalues).

    Intuición: vectores que no cambian de dirección

    Imagina una matriz que representa una transformación lineal —por ejemplo, una matriz de “shear” (cizallamiento), que deforma un cuadrado en un paralelogramo.
    En la mayoría de los casos, todos los vectores cambian de dirección al aplicar la transformación… excepto algunos muy particulares. Esos vectores especiales mantienen su dirección (aunque pueden cambiar su longitud). Por eso decimos que son autovectores.

    Ejemplo de una transformación lineal:

    import numpy as np
    
    M = np.array([[2, 1],
                  [1, 3]])
    
    square = np.array([[0, 0, 1, 1, 0],
                       [0, 1, 1, 0, 0]])
    transformed = M @ square
    Código de la grafica

    Código Python con Matplotlib

    fig, ax = plt.subplots(figsize=(8,8))
    ax.plot(square[0], square[1], 'b--', label='Original')
    ax.plot(transformed[0], transformed[1], 'r-', label=f'Shear con b={b}')
    
    ax.set_xlim(-1, 3)
    ax.set_ylim(-1, 3)
    ax.axhline(0, color='black')
    ax.axvline(0, color='black')
    ax.set_aspect('equal')
    ax.legend()
    plt.show()

    Definición

    Un vector \( \vec{v} \) es un autovector de una matriz \( M \) si, al aplicar la matriz transformadora sobre él, el resultado es el mismo vector escalado por un número \( \lambda \):

    $$M \vec{v} = \lambda \vec{v}$$

    Donde:

    • \( M \) → es una matriz cuadrada \(n \times n\)
    • \( \vec{v} \) → es un autovector
    • \( \lambda \) → es el autovalor asociado

    Este número \( \lambda \) indica cuánto se estira o encoge el vector cuando la matriz actúa sobre él.

    Interpretación geométrica

    • Si \( \lambda > 1 \): el vector se alarga.
    • Si \( 0 < \lambda < 1 \): el vector se encoge.
    • Si \( \lambda < 0 \): el vector cambia de sentido (se invierte).
    • Si \( \lambda = 1 \): el vector queda igual.

    Calculando los eigenvectors y eigenvalues

    Continuamos con el ejemplo inicial:

    import numpy as np
    
    # Calcular eigenvalores y eigenvectores
    w, V = np.linalg.eig(M)
    
    print("\nEigenvalores:\n", w)
    print("\nEigenvectores (columnas):\n", V)

    Salida:

    Eigenvalores:
     [1.38196601 3.61803399]
    
    Eigenvectores (columnas):
     [[-0.85065081 -0.52573111]
     [ 0.52573111 -0.85065081]]
    Código de la grafica

    Código Matplotlib

    import matplotlib.pyplot as plt
    fig, ax = plt.subplots(figsize=(8,8))
    
    # Cuadrado original (azul) y transformado (rojo)
    ax.plot(square[0], square[1], 'b--', label='Original (cuadrado unidad)')
    ax.plot(transformed[0], transformed[1], 'r-', label='Transformado M·S')
    
    # Ejes
    ax.axhline(0, color='black', linewidth=1)
    ax.axvline(0, color='black', linewidth=1)
    
    # Eigenvectores
    for i in range(len(w)):
        v = V[:, i]            # vector propio
        Mv = M @ v             # su transformación
        λ = w[i]
    
        # Dibuja el eigenvector (azul)
        ax.quiver(0, 0, v[0], v[1], angles='xy', scale_units='xy', scale=1,
                  color='blue', width=0.007, label=fr'$v_{i+1}$')
    
        # Dibuja el vector transformado (rojo)
        ax.quiver(0, 0, Mv[0], Mv[1], angles='xy', scale_units='xy', scale=1,
                  color='red', width=0.007, label=fr'$M v_{i+1} = \lambda_{i+1} v_{i+1}$')
    
        # Muestra texto con el eigenvalor
        ax.text(Mv[0]*1.1, Mv[1]*1.1, fr'$\lambda_{i+1}={λ:.2f}$', color='red', fontsize=10)
    
    ax.set_xlim(-4, 4)
    ax.set_ylim(-4, 4)
    ax.set_aspect('equal', adjustable='box')
    ax.legend(loc='upper left', facecolor='none', edgecolor='none')
    ax.set_title("Transformación lineal y Eigenvectores", fontsize=14)
    ax.set_xlabel("x")
    ax.set_ylabel("y")
    plt.grid(True)
    plt.show()
    

    Matrices simétricas

    Cuando una matriz es simétrica (es decir, \( M = M^T \)), se cumple algo muy útil:

    • Todos sus autovectores son perpendiculares entre sí.
    • Sus autovalores son reales.

    Por ejemplo:

    A = np.array([[4, 1],
                  [1, 4]])
    
    autovalores, autovectores = np.linalg.eig(A)
    print("Autovalores:", autovalores)
    print("Autovectores:\n", autovectores)
    
    print("Producto punto entre los autovectores:", np.dot(autovectores[:,0], autovectores[:,1]))

    La salida mostrará que el producto punto es 0, confirmando que los autovectores son ortogonales.

    Autovalores: [5. 3.]
    Autovectores:
     [[ 0.70710678 -0.70710678]
     [ 0.70710678  0.70710678]]
    Producto punto entre los autovectores: 0.0

    Aplicaciones en ciencia de datos

    Los eigenvectores y eigenvalores son fundamentales en data science:

    Análisis de Componentes Principales (PCA)

    • Qué hace: Reduce dimensiones de un dataset encontrando los eigenvectores de la matriz de covarianza.
    • Ejemplo: Dataset Iris (150×4) → eigenvectores indican las direcciones de mayor variación (ej: longitud vs ancho de pétalo).

    Redes Neuronales

    • Eigenvectores optimizan transformaciones en capas de redes profundas.
    • Ejemplo: Ajustar pesos para maximizar patrones.

    Procesamiento de Imágenes

    • Eigenvectores en eigenfaces identifican características faciales clave.
    • Ejemplo: Reconocimiento facial en apps de seguridad.

    Sistemas Dinámicos

    • Modelan cómo cambian datos con el tiempo (ej: predicciones financieras).
    • Eigenvalores determinan la estabilidad de los sistemas.

    Historia real: En 2024, Spotify usó eigenvectores en su sistema de recomendaciones para identificar patrones en gustos musicales, mejorando la precisión en un 10%.

    Cómo encontrar los Eigenvalues y Eigenvectors

    Para cualquier matriz \(M\):

    1. Primero encontramos todos los eigenvalores λ.
    2. Luego, usando esos eigenvalores, encontramos los eigenvectores correspondientes.

    La ecuación base \(M \vec{v} = \lambda \cdot \vec{v}\) será la clave de todo.

    Pero para trabajar con ella algebraicamente, vamos a transformarla un poco.

    La matriz identidad

    Necesitamos la matriz especial llamada la matriz identidad, que se denota por \(I\). La matriz identidad es una matriz cuadrada con unos en la diagonal principal (de arriba a la izquierda hasta abajo a la derecha) y ceros en todas las demás posiciones. Ya la vimos como ejemplo anteriormente en el articulo de las matrices.

    Por ejemplo, la matriz identidad de tamaño 3×3 es:

    $$I = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1\end{bmatrix}$$

    Y se llama “identidad” porque, al multiplicarla por cualquier matriz o vector, el resultado es exactamente el mismo.

    Podemos decir que: \(I \cdot M = M\) y tambien que: \(I \cdot v = v\)

    Manipulamos la ecuación para llegar al sistema característico

    Volvamos a nuestra ecuación:

    $$M \vec{v} = \lambda \cdot \vec{v}$$

    Podemos escribir el lado derecho como \(\lambda I \cdot v\), ya que \(I \cdot v.\).

    Entonces la ecuación queda así:

    $$M \vec{v} = \lambda I \cdot \vec{v}$$

    Restamos el término del lado derecho en ambos lados:

    $$M \cdot \vec{v} \ – \lambda I \cdot \vec{v} = 0 $$

    Sacamos vvv como factor común (como si fuera un número):

    $$(M \ – \lambda I) \cdot \vec{v} = 0 $$

    Y esta ecuación es fundamental: se conoce como la ecuación característica.


    La condición de existencia de eigenvectores

    Esta ecuación tiene dos tipos de soluciones posibles:

    1. La trivial, cuando \(v=0\).
      Pero ese vector no nos dice nada (no tiene dirección ni longitud), así que lo descartamos.
    2. La no trivial, cuando \(v≠0\).
      Para que exista esta solución, debe cumplirse una condición especial.

    Recuerda una propiedad del álgebra lineal:

    Una ecuación de la forma \(A \cdot v=0\) solo tiene una solución no trivial \(v≠0\) si la matriz A es singular, es decir, su determinante es igual a cero.

    Aplicando esto a nuestra ecuación \((M \ – \lambda I) \cdot \vec{v} = 0 \), la condición será: \(det(M \ – \lambda I) \cdot \vec{v} = 0 \)

    Esta ecuación nos permitirá encontrar los valores de \( \lambda \), los eigenvalores.


    Interpretación geométrica: el área que se hace cero

    Detrás de todo esto hay una idea visual muy poderosa.

    Imagina que tienes una matriz \(M\) que transforma puntos del plano \(XY\). Puedes representarla como una transformación del cuadrado unitario (un cuadrado de lado 1 anclado en el origen).

    Cuando multiplicas \(M\) por las coordenadas de los vértices de ese cuadrado, obtienes un nuevo cuadrilátero. En general, este nuevo cuadrilátero es un paralelogramo.

    • Si \(M\) solo escala el cuadrado, obtienes un rectángulo.
    • Si además deforma el cuadrado (por ejemplo, en un cizallamiento), obtienes un paralelogramo inclinado.

    El área de ese paralelogramo es una medida de cuánto “estira” o “encoge” la transformación de \(M\).
    Y el determinante de la matriz está directamente relacionado con esa área.

    Cuando el determinante es cero, significa que la transformación ha colapsado el plano en una línea o un punto, es decir, ha perdido una dimensión. Eso ocurre exactamente cuando estamos en un eigenvalor, porque en ese caso el espacio queda “aplastado” en una dirección particular: la del eigenvector.


    Ejemplo visual con una matriz 2×2

    Imaginemos una matriz genérica \(M\) de 2×2:

    $$M = \begin{bmatrix} a & b \\ c & d \end{bmatrix}$$

    Y tomemos el cuadrado unitario cuyos vértices son (0,0), (1,0), (1,1) y (0,1).

    Cuando aplicamos \(M\) sobre esos puntos, el cuadrado se transforma en un paralelogramo cuyos vértices vienen dados por los productos matriciales:

    $$M \cdot S$$

    donde \(S\) contiene las coordenadas de los vértices del cuadrado.
    El área de ese nuevo paralelogramo se puede calcular directamente como:

    $$\text{Área} = ad – bc$$

    que es precisamente el determinante de \(M\).

    Así que cuando el determinante \(ad−bc=0\), el paralelogramo “se aplasta” y pierde área. Geométricamente, eso es lo que ocurre cuando hay un eigenvalor: la transformación ya no conserva el área y “colapsa” el espacio en una dirección.


    Cálculo con Python: encontrar los eigenvalores

    Ejemplo con matriz 2×2.

    $$M = \begin{bmatrix} 2 & 1 \\ 1 & 2 \end{bmatrix}$$

    M = np.array([[2, 1],
                  [1, 2]])

    Calculamos eigenvalores y eigenvectores

    eigenvalores, eigenvectores = np.linalg.eig(M)
    
    print("Matriz M:")
    print(M)
    
    print("\nEigenvalores:")
    print(eigenvalores)
    
    print("\nEigenvectores (por columnas):")
    print(eigenvectores)
    Eigenvalores:
    [1.38196601 3.61803399]
    
    Eigenvectores (por columnas):
    [[-0.85065081 -0.52573111]
     [ 0.52573111 -0.85065081]]

    Ejemplo con matriz 3×3.

    M3 = np.array([
        [4, -2, 1],
        [0, 3, -1],
        [0, 0, 2]
    ])
    
    eigenvalores3, eigenvectores3 = np.linalg.eig(M3)
    
    print("Matriz M3:")
    print(M3)
    
    print("\nEigenvalores:")
    print(eigenvalores3)
    
    print("\nEigenvectores (por columnas):")
    print(eigenvectores3)
    Matriz M3:
    [[ 4 -2  1]
     [ 0  3 -1]
     [ 0  0  2]]
    
    Eigenvalores:
    [4. 3. 2.]
    
    Eigenvectores (por columnas):
    [[1.         0.89442719 0.33333333]
     [0.         0.4472136  0.66666667]
     [0.         0.         0.66666667]]

  • Tipos de matrices y operaciones

    ¿Qué es una matriz?

    Si los vectores son puntos en un mapa, las matrices son el mapa completo: una matriz es una cuadrícula de números organizada en filas y columnas. Puedes pensarla como un conjunto de vectores fila o vectores columna, dependiendo del caso.

    Matemáticamente, se escribe como un conjunto rectangular o cuadrado de números. Cada número dentro de la matriz se llama elemento, y se identifica por su posición: \(a_{ij}\) es el elemento que está en la fila i y la columna j.

    $$ A = \begin{bmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ a_{31} & a_{32} & a_{33} \end{bmatrix} $$

    Aquí la matriz \(A\) tiene 3 filas y 3 columnas, por lo tanto, su dimensión es \(3 \times 3\).

    • Filas: 3 (cada una es un vector)
    • Columnas: 3 (cada una es un vector)
    • Dimensión: \(3×3\) (filas x columnas)

    Dimensiones

    Scalar

    $$a = 1$$

    1D: vector columna o vector fila, según la orientación

    $$\vec{v} = \begin{bmatrix}v_{11} \\ v_{21} \\ v_{31} \\ \ldots \\ v_{3n} \end{bmatrix}$$

    $$\vec{v} = \begin{bmatrix}v_{11} \ v_{12} \ v_{13} \ \ldots \ v_{1n} \end{bmatrix}$$

    • 2D Matriz

    $$A = \begin{bmatrix}1 & 2 \\ 3 & 4 \end{bmatrix}$$

    • 3D Tensor

    $$T_{ijk} = \begin{bmatrix}[1 & 2] & [3 & 4] \\ [5 & 6] & [7 & 8]\end{bmatrix}$$

    Tipos de matrices

    Matriz fila y matriz columna vistas anteriormente en la dimension 1D

    Matriz cuadrada: tiene el mismo número de filas y columnas \( (n \times n) \).

    $$ A = \begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix} $$

    • Diagonar mayor: a = [1 , 5 , 9]
    • Diagonal menor: a = [3 , 5 , 7]

    Matriz de identidad o unidad: tiene 1 en la diagonal principal y 0 en el resto.

    $$A = \begin{bmatrix}1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}$$

    Matriz Escalar: Todos los elementos de la diagonal son iguales.

    $$A = \begin{bmatrix}3 & 0 & 0 \\ 0 & 3 & 0 \\ 0 & 0 & 3 \end{bmatrix}$$

    Matriz triangular superior y triangular inferior.

    Superior: debajo de la diagonal todos ceros

    $$A = \begin{bmatrix}1 & 2 & 3 \\ 0 & 5 & 6 \\ 0 & 0 & 9 \end{bmatrix}$$

    Inferior: encima de la diagonal todos ceros

    $$A = \begin{bmatrix}1 & 0 & 0 \\ 4 & 5 & 0 \\ 7 & 8 & 9 \end{bmatrix}$$

    Matriz Diagonal: los elementos que no están en la diagonal principal son ceros.

    $$A = \begin{bmatrix}1 & 0 & 0 \\ 0 & 5 & 0 \\ 0 & 0 & 9 \end{bmatrix}$$

    Matriz nula: todos los elementos son 0.

    $$A = \begin{bmatrix}0 & 0 & 0 \\ 0 & 0 & 0 \\ 0 & 0 & 0 \end{bmatrix}$$

    La matriz identidad, por ejemplo, es clave porque actúa como el “1” de la multiplicación matricial:

    $$I = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} \quad \Rightarrow \quad A \cdot I = A$$

    Matriz traspuesta: Se obtiene intercambiando filas por columnas:

    $$ A = \begin{bmatrix} 1 & 2 & 3 & 4 & 5 \\ 6 & 7 & 8 & 9 & 10 \end{bmatrix} $$

    $$ A^T= \begin{bmatrix} 1 & 6 \\ 2 & 7 \\ 3 & 8 \\ 4 & 9 \\ 5 & 10\end{bmatrix} $$

    Matriz simétrica: cuando es igual a su traspuesta.

    $$ A = \begin{bmatrix} 2 & 4 & -8 \\ 4 & -3 & 5 \\ -8 & 5 & 0 \end{bmatrix} $$

    $$ A^T= \begin{bmatrix} 2 & 4 & -8 \\ 4 & -3 & 5 \\ -8 & 5 & 0 \end{bmatrix} $$

    Matrices como datos

    En ciencia de datos, todo lo que analizamos puede representarse con matrices:

    • Un dataset es una matriz donde cada fila es una observación y cada columna una variable.
    • Una imagen es una matriz de píxeles, y si es en color, es una matriz 3D , también llamado Tensor.
    • Una serie temporal puede representarse como una matriz con las variables en columnas y el tiempo en filas.

    Por ejemplo, una imagen en blanco y negro de 3×3 se puede representar así:

    $$ I =\begin{bmatrix}0 & 255 & 0 \\ 255 & 0 & 255 \\ 0 & 255 & 0\end{bmatrix}$$

    donde cada número representa la intensidad del color.

    Matrices como funciones

    También llamada Matrices Transformadoras, son matrices que actuan como una función que transforma datos.

    Una transformación lineal es una función que toma vectores como entrada y devuelve otros vectores como salida. Las transformaciones lineales pueden:

    • Estirar o encoger figuras (cambio de escala)
    • Girarlas (rotación)
    • Reflejarlas (simetría)
    • Aplanarlas (proyección)
    • Combinarlas (rotar + escalar, por ejemplo)

    Pero no pueden doblar, curvar, ni mover los puntos de forma no proporcional (eso sería una transformación no lineal).

    Por ejemplo, en geometría o visión por computador, una matriz de rotación de un ángulo \((\theta)\) es:

    $$R(\theta) = \begin{bmatrix}\cos \theta & -\sin \theta \\ sin \theta & \cos \theta \end{bmatrix}$$

    Aplicar esta matriz a un vector rota el punto alrededor del origen.

    Operaciones con Matrices

    Suma y resta de matrices

    Dos matrices se pueden sumar o restar solo si tienen el mismo tamaño. Se suman los elementos correspondientes en cada matriz:

    $$ A + B = \begin{bmatrix} a_{11}​+b_{11} & a_{12}​+b_{12}​ \\ ​a_{22}​+b_{22}​​ & a_{21}+b_{21} \end{bmatrix}$$

    Multiplicación por un scalar

    Cada elemento de la matriz se multiplica por el número (escalar):

    $$ 2A = \begin{bmatrix} 2a_{11} & 2a_{12}​ \\ ​2a_{22}​​​ & 2a_{21​​​} \end{bmatrix}$$

    Producto de matrices

    Para poder multiplicar dos matrices es necesario que el número de columnas de la primera matriz sea igual al número de filas de la segunda. Para realizar la multiplicación se multiplican los elementos de cada fila de A por cada elemento de las columnas de B y se suman los resultados.

    $$(A \times B)_{ij} = \begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix} \begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix}$$

    $$ = \begin{bmatrix} 1 \cdot 5 + 2 \cdot 7 & 1 \cdot 6 + 2 \cdot 8 \\ 3 \cdot 5 + 4 \cdot 7 & 3 \cdot 6 + 4 \cdot 8\end{bmatrix} $$

    $$ = \begin{bmatrix} 19 & 22 \\ 43 & 50 \end{bmatrix} $$


    Operaciones de Matrices con Python

    • Crear matrices con funciones convenientes, Numpy ofrece varias funciones para crear matrices comunes rapidamente:
    A = np.ones((3, 4))   # Matriz 3x4 llena de unos
    B = np.zeros((3, 3))  # Matriz 3x3 llena de ceros
    C = np.ones((2, 2)) * 4  # Matriz 2x2 llena de cuatros
    
    print("A:\n", A)
    print("B:\n", B)
    print("C:\n", C)
    A:
     [[1. 1. 1. 1.]
     [1. 1. 1. 1.]
     [1. 1. 1. 1.]]
    B:
     [[0. 0. 0.]
     [0. 0. 0.]
     [0. 0. 0.]]
    C:
     [[4. 4.]
     [4. 4.]]
    • Propiedad .shape: conocer las dimensiones de la matriz
    print(A.shape)
    (3, 4)
    • Indexación: acceder a elementos, fila y columnas
    M = np.array([[1, 2, 3],
                  [4, 5, 6]
                  [7, 8, 9]])
                  
    valor = M[4, 5]  # valor en la fila 5, columna 6 (Python indexa desde 0)
    fila = M[1, :]  # acceder a una fila completa
    columna = M[:, 2]  # acceder a una columna completa
    
    print(valor)
    print(fila)
    print(columna)
    6
    [4 5 6]
    [3 6 9]
    • Suma y resta de matrices
    C = A + B
    D = B - A
    • Multiplicación por escalar
    E = 3 * A
    • Producto de matrices
    C = A @ B
    # tambien se puede usar:
    np.dot(A, B)
    • Transpuesta de una matriz
    print("A^T =\n", A.T)
    • Matriz identidad
    I = np.eye(2)
    print("Matriz identidad:\n", I)
    
    print("A @ I =\n", A @ I)
    • Determinante y matriz inversa
    det_A = np.linalg.det(A)
    inv_A = np.linalg.inv(A)

    6. En resumen

    • Las matrices son la base del álgebra lineal y de los modelos de datos.
    • En Machine Learning, cada conjunto de entrenamiento es una gran matriz.
    • En visión por computador, las imágenes son matrices.
    • En análisis estadístico, las transformaciones de los datos se hacen con multiplicaciones matriciales.

    Por eso, entender cómo funcionan es esencial: todo modelo, por complejo que parezca, se reduce a operaciones con vectores y matrices.

  • Vectores: la brújula del álgebra lineal y la ciencia de datos

    Imagina que los datos son como puntos en un mapa. Un vector es la flecha que describe dónde está ese punto y cómo llegar a él. En data science, los vectores son la forma más básica y poderosa de representar datos, desde características de un cliente hasta píxeles en una imagen.

    El vector es el elemento fundamental y raíz de toda el algebra lineal.

    Los vectores no son solo un concepto matemático para escribir ecuaciones de forma concisa.
    También son herramientas fundamentales para codificar información compleja, desde posiciones y velocidades hasta fuerzas y movimientos en varias dimensiones.


    ¿Qué es un vector?

    Más allá de ser una lista ordenada de números, un vector puede pensarse como: cualquier cosa que tenga una dirección y una magnitud.

    Es una lista ordenada de números que describe una posición o característica en un espacio. En data science, cada vector representa un punto de datos y cada fila de tu dataset es un vector.

    Esta definición es la que usan los físicos. Por ejemplo:

    • Dirección: hacia dónde apunta el vector.
    • Magnitud: qué tan grande es, también llamada norma del vector.

    Ejemplos

    Supongamos que describes a una persona por su edad y salario:

    • Vector: \([25, 50000]\)
      • 25: Edad (en años)
      • 50000: Salario (en euros)

    Visualmente:

    • Un vector es una flecha en un plano:
      • Origen: \((0,0)\)
      • Punta: \((25, 50000)\)
    • En 2D, se ve como una línea desde el origen al punto.

    Dimensiones

    • 2D: \([x, y]\) (ej: edad, salario)
    • 3D: \([x, y, z]\) (ej: edad, salario, experiencia)
    • n-D: \([x₁, x₂, …, xₙ]\) (datasets con muchas columnas)

    De la Ecuación al Movimiento

    Imaginemos una pelota lanzada desde el origen que en términos de vectores seria la posición \((0,0)\) en un espacio bidimensional. La posición de la pelota en cada instante se puede codificar como un vector \( \mathbf{p} = (p_1, p_2) \), donde:

    • \(p_1 = 5\) representa la posición horizontal \(x\)
    • \(p_2 = 4\) representa la posición vertical \(y\).

    Así, en lugar de seguir las coordenadas de los ejes por separado, podemos usar un solo vector para describir la posición de la pelota.

    $$ \vec{p} = \begin{bmatrix}5\\4\end{bmatrix}$$

    Si representamos \(\vec{p}\)​ en un plano cartesiano, se vería como una flecha que parte del origen (0,0) y termina en (5,4). La flecha tiene una dirección (hacia dónde apunta) y una longitud, que nos dice qué tan lejos está el punto final del origen. Para graficar podemos utilizar ax.arrow() en Matplotlib.

    Código de la grafica

    Código en Python Matplotlib

    import matplotlib.pyplot as plt
    
    # Crear figura y ejes
    fig, ax = plt.subplots(figsize=(8, 8))
    
    # Dibujar el vector desde (0,0) hasta (5,4)
    ax.arrow(0, 0, 5, 4, head_width=0.3, head_length=0.4, fc='blue', ec='blue', linewidth=2)
    
    # Marcar el punto final del vector
    ax.plot(5, 4, 'o', markersize=6, color='blue')
    ax.plot(0, 0, 'o', markersize=6, color='blue')
    ax.text(5.6, 4, r"$\vec{v} = [5,\, 4]$", fontsize=14, color='blue')
    
    # Ejes centrados
    ax.spines['left'].set_position('zero')
    ax.spines['bottom'].set_position('zero')
    
    # Quitar bordes superior y derecho
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    
    # Color y grosor de los ejes
    for spine in ['left', 'bottom']:
        ax.spines[spine].set_color('gray')
        ax.spines[spine].set_linewidth(1)
    
    # Límites y cuadrícula
    ax.set_xlim(-6, 8)
    ax.set_ylim(-6, 8)
    ax.grid(False)
    
    # Tamaño de los números de los ejes
    ax.tick_params(axis='both', which='major', labelsize=10)
    
    # Etiquetas y título
    ax.set_xlabel(r"$x$", fontsize=14, loc="right")
    ax.set_ylabel(r"$y$", fontsize=14, loc="top", rotation=0)
    ax.set_title("Vector", pad=20)
    
    # Guardar y mostrar
    plt.savefig("vector.png", transparent=True, dpi=300)
    plt.show()
    

    La norma (longitud del vector): cuánto ha viajado la pelota

    Esa longitud, también llamada norma, nos dice qué tan grande es el vector.
    Se denota con dos barras verticales, así: \( ||\mathbf{p}|| \) Para saber qué tan lejos está la pelota desde el origen, usamos la norma del vector:

    $$||\mathbf{p}|| = \sqrt{p_1^2 + p_2^2}$$

    Esta ecuación se deriva directamente del teorema de Pitágoras: la hipotenusa de un triángulo rectángulo es la raíz cuadrada de la suma de los cuadrados de sus catetos. Por ejemplo, si \(p_1 = 5\) y \(p_2 = 4\), la norma es:

    $$||\mathbf{p}|| = \sqrt{5^2 + 4^2} \approx 6.40$$

    La norma siempre da como resultado un número positivo: la distancia desde el origen hasta el punto final del vector.

    Vectores en dimensiones superiores

    Si la pelota se moviera en un espacio tridimensional, solo agregamos un componente más:

    $$\mathbf{p} = (p_1, p_2, p_3), \quad $$

    $$||\mathbf{p}|| = \sqrt{p_1^2 + p_2^2 + p_3^2}$$

    Y si tuviéramos un vector en \(N\) dimensiones, simplemente añadimos cada componente al cálculo de la norma:

    $$||\mathbf{p}|| = \sqrt{p_1^2 + p_2^2 + \dots + p_N^2}$$

    Esto hace que los vectores sean muy poderosos para manejar información compleja de manera compacta.

    Aplicaciones de los vectores en física

    Los vectores nos permiten representar de manera eficiente:

    • Posición: dónde se encuentra un objeto.
    • Velocidad: dirección y rapidez del movimiento.
    • Fuerza: hacia dónde actúa y cuán intensa es.

    Además, con operaciones como suma, resta, multiplicación por escalar o producto punto, podemos combinar vectores y calcular efectos resultantes de manera simple.

    Por ejemplo, en nuestra pelota de béisbol, un vector nos permite:

    • Conocer simultáneamente su posición en \(x\) y \( y\) ,
    • Medir su distancia desde el punto de lanzamiento con la norma,
    • Y si quisiéramos incluir velocidad o aceleración, usar vectores de mayor dimensión para mantener todo compacto y manejable.

    Dos propiedades clave de un vector

    1. Dirección: hacia dónde apunta.
    2. Magnitud: cuán grande es, calculable con la norma.

    En cualquier número de dimensiones, esta regla sigue siendo válida, lo que convierte a los vectores en herramientas universales para describir información física y multidimensional.

    Operaciones con Vectores

    Los vectores son poderosos porque puedes operarlos para descubrir patrones. Aquí las operaciones más importantes:

    Suma de Vectores

    si tenemos dos vectores de la misma dimensión:

    $$ \vec{u} = \begin{bmatrix}u_1\\u_2\\u_3\end{bmatrix}, \vec{v} = \begin{bmatrix}v_1\\v_2\\v_3\end{bmatrix}$$

    La suma es simplemente sumar cada componente correspondiente:

    $$ \vec{u} + \vec{v}= \begin{bmatrix}u_1+v_1\\u_2+v_2\\u_3+v_3\end{bmatrix}$$

    Esto es útil porque cuando sumamos vectores estamos combinando información de manera ordenada, igual que antes combinábamos cantidades de manzanas, naranjas y pan. La suma de vectores es la primera forma de “agrupar información” en un vector.

    Multiplicación por escalar

    Si tenemos un número \(k\) y un vector \(\vec{v}\), multiplicamos cada componente por ese número:

    $$ k \cdot \vec{v}= k \cdot \begin{bmatrix}v_1\\v_2\\v_3\end{bmatrix} = \begin{bmatrix}kv_1\\kv_2\\kv_3\end{bmatrix}$$

    Esto sirve para escalar vectores, como cuando queremos “duplicar” o “reducir” una cantidad.

    Producto Escalar (Dot Product)

    Dot Product: Mide la similitud entre dos vectores.

    El producto escalar es una operación entre dos vectores que produce un número, a diferencia de la suma o resta de vectores, que produce otro vector.

    Si tenemos dos vectores de la misma dimensión:

    $$ \vec{a} = \begin{bmatrix}a_1\\a_2\\.\\.\\.\\a_n\end{bmatrix}, \vec{b} = \begin{bmatrix}b_1\\b_2\\.\\.\\.\\b_n\end{bmatrix}$$

    el producto punto se define como:

    $$ \vec{a} \cdot \vec{b} = a_1b_1 + a_2b_2 + . . . + a_nb_n$$

    O, lo que es lo mismo:

    $$ \vec{a} \cdot \vec{b} = \sum ^{n} _ {i=1} a_ib_i$$

    Cada componente se multiplica componente por componente, y luego se suman los resultados.

    Ejemplo:

    Supongamos que tienes un presupuesto de $30 y quieres comprar: manzanas, naranjas y peras.

    Definimos:

    • Vector de cantidades compradas

    $$ \vec{g} = \begin{bmatrix}g_1\\g_2\\g_3\end{bmatrix} = \begin{bmatrix}4\\3\\2\end{bmatrix} $$

    • Vector de precios de productos:

    $$ \vec{c} = \begin{bmatrix}c_1\\c_2\\c_3\end{bmatrix} = \begin{bmatrix}2\\3\\5\end{bmatrix}$$

    Entonces, el total gastado se puede escribir como:

    $$ Total= \vec{c} \cdot \vec{g} $$

    $$ T= c_1g_1 + c_2g_2 + c_3g_3 $$

    $$ T = 2⋅4+3⋅3+5⋅2$$

    $$ T =8+9+10=27$$

    Interpretación geométrica

    Geométricamente, el producto punto mide cuánto se parecen o se alinean dos vectores en dirección:

    $$\vec{a} \cdot \vec{b} = |\vec{a}|\: |\vec{b}| \: cos⁡(θ)$$

    • Si \(θ=0°\): los vectores están en la misma dirección → producto punto positivo y máximo.
    • Si \(θ=90°\): son perpendiculares → producto punto = 0.
    • Si \(θ>90°\): apuntan en direcciones opuestas → producto punto negativo.

    Esto significa que el producto punto mide cuánto “apuntan en la misma dirección” dos vectores.

    Ecuaciones como producto escalar

    Entiende la idea base

    La expresión general:

    $$y=a_1​x_1​+a_2​x_2​+⋯+a_n​x_n​$$

    Es el punto de partida que lleva directamente a la forma matricial de los sistemas lineales.

    Partimos del sistema:

    $$\begin{cases} 2x + 3y = 30 \\ x + y = 12 \end{cases}$$

    Es el resultado de un producto punto entre dos vectores.

    $$\begin{bmatrix} 2 & 3 \\ 1 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix} = \begin{bmatrix} 30 \\ 12 \end{bmatrix}$$

    Significado de las partes:

    PartesSignificado
    $$\begin{bmatrix} 2 & 3 \\ 1 & 1 \end{bmatrix}$$Matriz de coeficientes: contiene los números que multiplican a las variables (los precios de las frutas).
    $$\begin{bmatrix} x \\ y \end{bmatrix}$$Vector de incógnitas: las variables que queremos encontrar (número de manzanas y naranjas).
    $$\begin{bmatrix} 30 \\ 12 \end{bmatrix}$$Vector de resultados: los valores en el lado derecho (total de dinero y total de frutas).

    La forma vectorial compacta del sistema matricial se expresa como:

    $$A\vec{x} = \vec{b}$$

    Donde:

    • \(A\) –> es la matriz de coeficientes
    • \(\vec{x}\) –> es el vector de incógnitas
    • \(\vec{b}\) –> es el vector de términos independientes

    Por tanto:

    $$A = \begin {bmatrix} 2 & 3 \\ 1 & 1 \end{bmatrix}, \vec{x} = \begin{bmatrix} x \\ y \end{bmatrix}, \vec{b} = \begin{bmatrix} 30 \\ 12 \end{bmatrix}$$

    Antes de hablar de matrices, hay una idea fundamental. Una ecuación lineal es un producto escalar.

    ones

    En resumen:

    • Una ecuación lineal = producto escalar
    • Un sistema = varios productos escalares
    • Una matriz = colección de vectores fila
    • Multiplicar matriz por vector = aplicar todos los productos escalares

    Usos del producto escalar en data science

    • Similitud de vectores (cosine similarity): En NLP, sistemas de recomendación o embeddings de palabras. Cuanto mayor sea este valor, más similares son los vectores.
    • Regresión lineal / Neuronas : Calcula la combinación lineal de las variables
    • Similitud del coseno : Mide cuánto se parecen dos vectores
    • PCA / Proyecciones : Proyecta un vector sobre una dirección
    • Distancias : Base para métricas vectoriales
    • Álgebra de matrices : Operación elemental en multiplicación de matrices

    Operaciones de vectores con Python

    Los vectores en Python se manejan con Numpy y se representan como listas:

    v = np.array([2, 3])
    w = np.array([1, -1])

    Suma y resta de vectores

    C = v + w
    d = v - w
    rint(f"{c}\n{d}")
    [3 2]
    [1 4]

    Multiplicación por escalar

    F = 2 * v
    print(F)
    [4 6]

    Producto escalar

    P = np.dot(v, w)
    print(P)
    P = np.dot(v, w)
    print(P)
    -1

    Norma del vector

    M = np.linalg.norm(v)
    print(M)
    3.605551275463989

    Vector unitario

    U = v / np.linalg.norm(v)
    print(U)
    [0.5547002  0.83205029]

    Ángulo entre vectores

    cos_theta = np.dot(v, w) / (np.linalg.norm(v) * np.linalg.norm(w))
    A = np.arccos(cos_theta)
    
    print(A)
    1.7681918866447774

  • Ecuaciones lineales la clave de la ciencia de datos

    ¿Por qué las ecuaciones lineales son clave en data science?

    Las ecuaciones lineales y los sistemas lineales son como el esqueleto de la data science. Son la base de algoritmos como la regresión lineal, los sistemas de recomendación y el análisis de datos en general. Imagina que cada punto de datos es una pieza de un rompecabezas: las ecuaciones lineales te ayudan a juntar las piezas para descubrir patrones.

    “Sin ecuaciones lineales, no habría machine learning moderno. Son el primer paso para transformar datos en decisiones.”

    ¿Qué es una ecuación lineal?

    Una ecuación lineal es una ecuación donde las variables están elevadas a la potencia 1 y multiplicadas por un coeficiente (no hay cuadrados ni raíces) y se combinan con sumas o restas.

    Ejemplo Simple

    $$3x + 2y = 30$$

    Como concepto está bien. ¿Pero cuál es el sentido de esto? ¿De dónde sale? La idea base de la ecuación lineal es una relación constante entre dos cosas. La ecuación lineal nace cuando dos magnitudes cambian de forma proporcional.

    Por ejemplo:

    Si vendes café a 2€ cada uno, el ingreso total depende linealmente del número de cafés vendidos.

    $$Ingreso = 2 \times \text{Número de cafés}$$

    Esto puede escribirse matemáticamente como

    $$y = 2x$$

    Donde:

    • xy: Variables (Ingreso, Café).
    • 2: Coeficientes (pesos de las variables)

    Esa es una relación lineal: cada vez que \(x\) aumenta 1, \(y\) aumenta 2. La tasa de cambio es constante. Visualmente esta ecuación representa una línea recta en un plano. Cada solución \((x, y)\) es un punto en esa línea.

    De ahí el nombre de lineal, porque describe una relación que se representa como una línea recta en un gráfico. Las ecuaciones lineales modelan situaciones donde:

    • El cambio es constante,
    • La relación entre variables es directa o proporcional.

    Por eso son la base de la modelización matemática, antes de llegar a modelos más complejos, todo empieza por asumir una relación lineal.

    Representar las ecuaciones

    En la forma general o modelo pendiente e intersección, toda ecuación lineal puede escribirse así:

    $$y=mx+b$$

    Donde:

    • \(b\) –> es el valor inicial o intersección con el eje Y: el valor de \(y\) cuando \(x=0\).
    • \(y\) –> valor en el eje vertical (dependiente)
    • \(x\) –> valor en el eje horizontal (independiente)
    • \(m\) –> es la pendiente, cuánto cambia \(y\) cuando \(x\) aumenta una unidad.
      • Si \(m > 0\) –> sube hacia la derecha (creciente)
      • Si \(m < 0\) –> baja hacia la derecha (decreciente)
      • Si \(m = 0\) –> la recta es horizontal
    grafica con los tipos de pendientes
    Código de la gráfica

    Código Python con Matplotlib

    import matplotlib.pyplot as plt
    fig, ax = plt.subplots(figsize=(8,8))
    ax.axline((0, 1), slope=2, color="red", linewidth=1, label="Creciente")
    ax.axline((0, -1), slope=-3, color="green", linewidth=1, label="Decreciente")
    ax.axline((0, 3), slope=0, color="blue",linewidth=1, label="Horizontal")
    
    # Ejes en el centro
    ax.spines['left'].set_position('zero')   # eje Y en x=0
    ax.spines['bottom'].set_position('zero') # eje X en y=0
    
    # Quitar bordes superior y derecho
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    
    # Cambiar color y grosor de los ejes (spines)
    for spine in ['left', 'bottom']:
        ax.spines[spine].set_color('black')
        ax.spines[spine].set_linewidth(2)
    
    # Límites y cuadrícula
    ax.set_xlim(-10, 10)
    ax.set_ylim(-10, 10)
    
    # tamaño de los numeros
    ax.tick_params(axis='both', which='major', labelsize=10)
    
    # Etiquetas y leyenda
    ax.set_xlabel(r"$x$", fontsize=14, loc="right")
    ax.set_ylabel(r"$y$", fontsize=14, loc="top", rotation=0)
    ax.legend()
    ax.set_title("Tipos de pendientes", pad=20)
    ax.legend(facecolor='none', edgecolor='none')
    ax.grid(False)
    plt.savefig("pendientes.png", transparent=True, dpi=300)
    plt.show()

    ¿Por qué las pendientes siempre avanzan a la derecha?

    Esto tiene que ver con cómo definimos el sistema de coordenadas cartesianas y el concepto de pendiente. Vamos a desglosarlo paso a paso:

    1. La pendiente mide cuánto cambia \(y\) cuando \(x\) cambia una unidad.
    2. Cuando calculamos la pendiente avanzamos de izquierda a derecha en el eje \(x\).
    3. Entonces la pendiente se interpreta como el cambio vertical que ocurre al movernos a la derecha.
    4. Por eso, al dibujar la recta, decimos que “avanza a la derecha” y sube o baja según \(x\).
    5. Si quisieras avanzar a la izquierda, sería simplemente \(x<0\) y la pendiente seguiría siendo la misma, solo que la “mirada” sería desde el otro extremo.

    En otras palabras: no es que la recta no exista hacia la izquierda, sino que matemáticamente la pendiente se mide tomando \(Δx\) (variación de x) positivo, lo que corresponde a moverse hacia la derecha.

    El sentido algebraico: equilibrio

    Desde el punto de vista algebraico, una ecuación es una igualdad entre dos expresiones que mantiene un equilibrio. Una ecuación lineal representa un equilibrio simple, sin potencias ni productos entre variables:

    $$2x+3y=30$$

    Significa que existen valores de \(x\) y \(y\) para los cuales la expresión de la izquierda \(2x+3y\)) tiene el mismo valor que el número de la derecha (30).

    • Cada punto \((x,y)\) que cumple esa igualdad está en equilibrio: pertenece a la recta.
    • Ambos lados deben ser iguales para que la ecuación se cumpla.
    • Una ecuación representa una condición de equilibrio o una restricción sobre los valores posibles de las variables.

    Desde el punto de vista algebraico, lo que hacemos con una ecuación es buscar los valores de las variables que la hacen verdadera. A eso lo llamamos resolver la ecuación. En este caso: \(2x+3y=30\) no tiene una única solución, sino infinitas combinaciones de \((x,y)\) que cumplen la igualdad (todas las que están sobre la recta).

    Si representamos todos los puntos \((x,y)\) que cumplen esa ecuación, obtenemos una recta en el plano cartesiano. Así, una ecuación lineal de dos variables es la expresión algebraica de una recta.

    Ejemplo: Ecuación lineal de las frutas

    Un problema clásico seria resolver cuantas manzanas y naranjas podemos comprar con 30€, donde las manzanas tienen un precio de 2€ y las naranjas de 3€. (Supón que puedes fraccionar las frutas).

    Este problema se resuelve con un ecuación lineal que se representa como sigue:

    $$2x + 3y = 30$$

    Donde:

    • 2 y 3 –> son los coeficientes (precios de las frutas)
    • \(x\)–> variable que representa las manzanas
    • \(y\) –> variable que representa las naranjas
    • 30 –> es el termino independiente (la constante)

    Representamos la ecuación en la forma general \(y=mx+b\):

    $$3y = -2x + 30$$

    Pasamos el 3 dividiendo y calculamos:

    $$y = \frac{2}{3}x – \frac{30}{3}$$

    $$y = -\frac{2}{3}x + 10$$

    Aquí tenemos:

    • \(m = – \frac{2}{3}\) –> pendiente de la recta.
    • \(b = 10\) –> la ordenada en el origen, o sea el punto donde la recta corta el eje Y.
    • Cuando \(x=0\): \(y=10\) –> la recta pasa por el punto \((0, 10)\).
    • Cuando \(y=0\): \(x=15\) → la recta pasa por el punto (15, 0):

    $$2x + 3y = 30$$

    $$2x + 3(0) = 30$$

    $$2x = 30$$

    $$2x = \frac{30}{2}$$

    $$x = 15$$

    Entonces tenemos ya dos puntos \((0,10)\) y \((15,0)\). Con estos dos puntos podemos trazar una recta que representa la ecuación. Cada punto en la recta, es una combinación de manzanas(\(x\)) y naranjas (\(y\)) que equivalen a una compra de 30€.

    Podemos calcular mas combinaciones de frutas posibles eligiendo los valores de \(x\) y calculando \(y\) en la ecuación de la forma pendiente – intersección.

    Por ejemplo, si \(x = 6\):

    $$y = – \frac{2}{3}x + 10$$

    $$y = – \frac{2}{3}(6) + 10$$

    $$y = – \frac{12}{3} + 10$$

    $$y = – 4 + 10 = 6$$

    Otra combinación de frutas y punto en la grafica seria \((6,6)\). Representemos gráficamente la ecuación.

    Código de la gráfica

    Código Python de Matplotlib

    import matplotlib.pyplot as plt
    fig, ax = plt.subplots(figsize=(8,8))
    ax.axline((0, 10), slope=-2/3, color="red", linewidth=2, label=r"$y = -\frac{2}{3}x + 10$")
    
    # Puntos específicos
    puntos = [(15,0), (0,10), (6,6)]
    for x, y in puntos:
        ax.plot(x, y, 'ko', markersize=6)              # dibujar punto
        ax.text(x + 0.5, y + 0.5, f"({x},{y})", fontsize=10, color='black')
    
    # Ejes en el centro
    ax.spines['left'].set_position('zero')   # eje Y en x=0
    ax.spines['bottom'].set_position('zero') # eje X en y=0
    
    # Quitar bordes superior y derecho
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    
    # Cambiar color y grosor de los ejes (spines)
    for spine in ['left', 'bottom']:
        ax.spines[spine].set_color('black')
        ax.spines[spine].set_linewidth(2)
    
    # Límites y cuadrícula
    ax.set_xlim(-20, 20)
    ax.set_ylim(-20, 20)
    
    # tamaño de los numeros
    ax.tick_params(axis='both', which='major', labelsize=10)
    
    # Etiquetas y leyenda
    ax.set_xlabel(r"$x$", fontsize=14, loc="right")
    ax.set_ylabel(r"$y$", fontsize=14, loc="top", rotation=0)
    ax.legend()
    ax.set_title("Grafica de la Ecuación", pad=20)
    ax.legend(facecolor='none', edgecolor='none')
    ax.grid(False)
    plt.savefig("ecuacion de las frutas.png", transparent=True, dpi=300)
    plt.show()

    Este sencillo problema de manzanas y naranjas nos muestra cómo las ecuaciones lineales nos permiten modelar relaciones entre variables de manera clara y predecible. Cada punto en la recta representa una combinación posible que satisface la restricción del problema (gastar 30 €), y la pendiente nos indica cómo cambiaría una variable si ajustamos la otra.

    En ciencia de datos y machine learning, este mismo concepto es fundamental: buscamos modelar relaciones entre variables para poder predecir, optimizar o tomar decisiones basadas en datos.


    Sistemas Lineales

    Un sistema lineal es un conjunto de ecuaciones lineales que resuelves juntas para encontrar valores que satisfagan todas.

    Supongamos que a nuestro problema anterior le añadimos una condición. Supón ahora que además de gastar 30 €, queremos comprar exactamente 12 frutas en total. Esa nueva condición se traduce en otra ecuación:

    $$x + y = 12$$

    Ahora tenemos dos ecuaciones y dos incógnitas \((x, y)\).

    $$\begin{cases} 2x + 3y = 30 \\ x + y = 12 \end{cases}$$

    Aquí, cada ecuación representa una recta en el plano cartesiano. El punto donde ambas rectas se cruzan es la combinación de frutas que cumple las dos condiciones al mismo tiempo: gastar 30 € y comprar exactamente 12 frutas. Existen varios métodos de resolver los sistemas de ecuaciones.

    Solución

    Método: Sustitución:

    1. Despeja una variable en una ecuación.
    2. Sustitúyela en la otra ecuación.
    3. Resuelve.

    Cuándo usarlo: Sistemas pequeños (2-3 ecuaciones).

    De la segunda ecuación despejamos \(x\) y sustituimos en la primera.

    $$x + y = 12$$

    $$x = 12 – y$$

    Sustituimos en la primera ecuación:

    $$2(12−y) + 3y = 30$$

    $$24− 2y + 3y = 30$$

    $$24 − 2y + 3y = 30$$

    $$24 + y = 30$$

    $$24 + y = 30$$

    $$y = 30 – 24 = 6$$

    Ahora sustituimos \(y\) en la segunda:

    $$x + y = 12$$

    $$x + 6 = 12$$

    $$x = 12 – 6 = 6$$

    Resultado: \(x=6,y=6\), o sea, 6 manzanas y 6 naranjas. En el gráfico el punto de intersección de las rectas es \((6,6)\).

    Método de eliminación con normalización

    1. Elige la variable pivote, busca ecuaciones en las que sea fácil trabajar; el objetivo es eliminarla.
    2. Normalizar las ecuaciones, divide cada ecuación por el coeficiente de esa variable.
    3. Restas unas ecuaciones de otras para eliminar la variable pivote.
    4. Te queda un sistema reducido con una variable menos.
    5. Repite el proceso, normaliza nuevamente si hace falta y elimina la siguiente variable hasta que tengas el valor de una variable.
    6. Sustituye ese valor en las ecuaciones de abajo hacia arriba en las ecuaciones anteriores hasta encontrar todas las variables

    Claves importantes

    • Dividir es opcional, pero ayuda a alinear ecuaciones
    • También puedes multiplicar y evitar decimales.
    • Restar ecuaciones es el paso central

    Cuándo usarlo: Sistemas pequeños (2-3 ecuaciones).

    $$\begin{cases} 2x + 3y = 30 \\ x + y = 12 \end{cases}$$

    Seleccionamos la variable \(x\) para normalizar la primera ecuación dividiendo la ecuación entre el coeficiente de \(x\) que es 2. La segunda ecuación no lo necesita, si fuera el caso, se dividiría la segunda ecuación por el coeficiente de su variable \(x\).

    $$x + 1.5 y = 15$$

    $$x + y = 12$$

    Restamos la ecuación 1 a la 2.

    $$x + y = 12$$

    $$x + 1.5 y = 15$$

    • \( x -x = 0 \)
    • \( 1y – 1.5y = 0.5y \)
    • \(12 – 15 = -3 \)

    resultado:

    $$-0.5y = – 3$$

    $$y = – \frac{3}{0.5}$$

    $$y = 6$$

    Ahora sustituimos \(y\) en la segunda:

    $$x + y = 12$$

    $$x + 6 = 12$$

    $$x = 12 – 6 = 6$$

    Resultado: \(x=6,y=6\).

    Con Matplotlib podemos graficar la recta solo con la pendiente y la intersección. En este caso para la segunda ecuación \(m = -1\) y \(b = 12\) .

    Código del gráfico

    Código Python de Matplotlib

    import matplotlib.pyplot as plt
    fig, ax = plt.subplots(figsize=(8,8))
    ax.axline((0, 10), slope=-2/3, color="red", linewidth=2, label=r"$y = -\frac{2}{3}x + 10$")
    ax.axline((0, 12), slope=-1, color="blue", linewidth=2, label=r"$y = -x + 12$")
    
    # Puntos específicos
    ax.plot(6, 6, 'ko', markersize=6)              # dibujar punto
    ax.text(x + 0.5, y + 0.5, f"({6},{6})", fontsize=10, color='black')
    
    # Ejes en el centro
    ax.spines['left'].set_position('zero')   # eje Y en x=0
    ax.spines['bottom'].set_position('zero') # eje X en y=0
    
    # Quitar bordes superior y derecho
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    
    # Cambiar color y grosor de los ejes (spines)
    for spine in ['left', 'bottom']:
        ax.spines[spine].set_color('black')
        ax.spines[spine].set_linewidth(2)
    
    # Límites y cuadrícula
    ax.set_xlim(-20, 20)
    ax.set_ylim(-20, 20)
    
    # tamaño de los numeros
    ax.tick_params(axis='both', which='major', labelsize=10)
    
    # Etiquetas y leyenda
    ax.set_xlabel(r"$x$", fontsize=14, loc="right")
    ax.set_ylabel(r"$y$", fontsize=14, loc="top", rotation=0)
    ax.legend()
    ax.set_title("Grafica de la Ecuación", pad=20)
    ax.legend(facecolor='none', edgecolor='none')
    ax.grid(False)
    plt.savefig("sistemas_de_ecuaciones.png", transparent=True, dpi=300)
    plt.show()

    Método 2: Matriz inversa

    • Determinar si la matriz \(A\) tiene inversa.
    • Aislar el vector de incógnitas \(\vec{x}\).
    • La forma de hacerlo no es dividiendo, porque no existe la división entre matrices, sino multiplicando por su inversa, denotada \(A^{-1}\).

    La ecuación de matriz inversa:

    $$\vec{x} = A^{-1} \vec{b}$$

    Resolviendo el sistema

    Para una matriz de dos ecuaciones como la del ejemplo:

    $$A = \begin{bmatrix} d & b \\ c & a \end{bmatrix}$$

    Determinar su inversa es:

    $$A^{-1} = \frac{1}{ad – bc} \begin{bmatrix} d & -b \\ -c & a \end{bmatrix}$$

    Entonces:

    $$A^{-1} = \frac{1}{(2)(1) – (3)(1)} \begin{bmatrix} 1 & -3 \\ -1 & 2 \end{bmatrix}$$

    $$A^{-1} = \frac{1}{-1}\begin{bmatrix} 1 & -3 \\ -1 & 2 \end{bmatrix}$$

    $$A^{-1} = \begin{bmatrix} -1 & 3 \\ 1 & -2 \end{bmatrix}$$

    • Este método solo funciona si \(A\) tiene inversa, lo que ocurre solo si el determinante de es distinto de cero, como en este caso.

    Paso final

    $$ \vec{x} = A^{-1}\vec{b}$$

    $$\vec{x}=\begin{bmatrix} -1 & 3 \\ 1& -2\end{bmatrix} \begin{bmatrix} 30 \\ 12 \end{bmatrix}$$

    $$\vec{x} = \begin{bmatrix} (-1)(30) + (3)(12) \\ (1)(30) + (-2)(12) \end{bmatrix}$$

    $$\vec{x} = \begin{bmatrix} -30 + 36 \\ 30 – 24 \end{bmatrix} = \begin{bmatrix} 6 \\ 6 \end{bmatrix}$$

    Resultado:

    $$x = 6 \\ y = 6$$

    Hay algunas operaciones básicas que usaremos constantemente:

    • Transposición (Aᵗ) → cambia filas por columnas.
    • Multiplicación de matrices (A·B) → combina vectores o sistemas.
    • Determinante (det(A)) → indica si el sistema tiene solución única.
    • Matriz inversa (A⁻¹) → nos permite resolver sistemas como \(x=A−1bx = A^{-1} bx=A−1b\).

    Estas herramientas son la base de muchos algoritmos modernos de machine learning y análisis de datos.

    Forma de la matriz aumentada

    La matriz aumentada es otra forma de representar un sistema de ecuaciones lineales, pero con un propósito muy concreto: resolverlo más fácilmente mediante operaciones por filas (como en el método de Gauss o Gauss-Jordan). Contiene toda la información numérica del sistema. Trabajar con ella evita reescribir las variables en cada paso.

    La matriz aumentada junta la matriz de coeficientes \(A\) y el vector de términos independientes \(\vec{b}\) en una sola matriz separada por una línea vertical:

    $$\begin{bmatrix}\begin{array}{cc|c}2 & 3 & 30 \\ 1 & 1 & 12 \end{array} \end{bmatrix}$$

    Esa barra vertical no tiene significado algebraico en sí, simplemente marca la frontera entre los coeficientes del sistema y los resultados.

    Método 3: Eliminación Gaussiana

    El objetivo de la eliminación es transformar esa matriz con operaciones por filas hasta una forma en la que las variables se lean directamente.
    Las operaciones permitidas (elementales por filas) son:

    1. Intercambiar dos filas.
    2. Multiplicar una fila por un escalar distinto de 0.
    3. Sumar a una fila un múltiplo de otra fila.

    Estas operaciones no cambian el conjunto de soluciones del sistema: son equivalencias algebraicas.

    Paso 1 — Elegir pivote (y, opcionalmente, intercambiar filas)

    En esta parte normalmente queremos que el primer elemento de la primera fila (posición (1,1)) sea un buen pivote (idealmente 1 y no 0). En nuestro caso la fila 2 ya tiene un 1 en la columna 1, así que intercambiamos las filas para facilitar cálculos:

    Operacion \(R_1 \leftrightarrow R_2\) (Row1 y Row2)

    $$\begin{bmatrix}\begin{array}{cc|c} 1 & 1 & 12 \\ 2 & 3 & 30 \end{array} \end{bmatrix}$$

    Paso 2 — Eliminar la variable \(x\) de las filas inferiores

    Qué se hace: queremos que en la columna del pivote (columna 1) todos los elementos excepto el pivote sean 0. Si el pivote fuese 0 habría que intercambiar filas para evitar dividir por 0.

    Elegimos multiplicar por 2 porque ese número es precisamente lo necesario para que, al restarlo, el coeficiente 2 de la fila 2 quede anulado \((2 − 2 = 0)\).

    Operación :\(R_2 \leftarrow R_2 – 2R_1\)

    Multiplicación de la fina 1 por 2:

    $$\begin{bmatrix}\begin{array}{cc|c} 2 & 2 & 24 \end{array} \end{bmatrix}$$

    Resta la fila multiplicada a la segunda, resultado:

    $$\begin{bmatrix}\begin{array}{cc|c} 1 & 1 & 12 \\ 0 & 1 & 6 \end{array} \end{bmatrix}$$

    • Al hacer esa resta estamos eliminando \(x\) de la segunda ecuación.
    • Esto reduce el sistema a uno triangular superior, que es más fácil de resolver.
    • La segunda fila ahora es \(0x+1y=6\), es decir \(y=6\). Hemos aislado una variable.

    Paso 3 — Resolver la última ecuación (retro-sustitución) o diagonalizar (Gauss–Jordan)

    Ya tenemos el valor de \(y=6\), si usamos retro-sustitucion

    Retro-sustitución para obtener \(x\) sustituyendo y en la primera ecuación:

    $$x+y=12x \rightarrow x + 6 = 12 \rightarrow \\ x = \frac{12}{6} \rightarrow x=6$$

    Solución por Gaus-Jordan

    Eliminamos el \(y\) en la primera fila:

    $$\begin{bmatrix}\begin{array}{cc|c} 1 & 1 & 12 \\ 0 & 1 & 6 \end{array} \end{bmatrix}$$

    Resultado:

    $$\begin{bmatrix}\begin{array}{cc|c} 1 & 0 & 6 \\ 0 & 1 & 6 \end{array} \end{bmatrix} \rightarrow x = 6 , y = 6$$

    Comprobación

    Comprobación en las ecuaciones originales:

    $$2x+3y=2(6)+3(6)\\ =12+18=30$$

    $$x+y=6+6=12$$

    Aplicaciones en Data Science

    La generalización del sistema lineal en una matriz aumentada es muy importante porque los modelos lineales en ciencia de datos funcionan exactamente igual:

    $$\vec{y} = A\vec{w} + \vec{ε}$$

    donde:

    • \(A\) es la matriz de datos (cada fila una observación, cada columna una variable)
    • \(\vec{w}\) son los pesos o coeficientes del modelo (lo que queremos estimar),,
    • \(\vec{y}\)​ son los valores observados o predichos.
    • \(\vec{ε}\) representa los errores o diferencias entre la predicción y los datos reales.

    Esa es exactamente la forma que adoptan los modelos lineales en ciencia de datos y machine learning.

    Resolver el sistema equivale a encontrar los valores de \(\vec{w}\) que mejor explican o ajustan los datos. Por eso, las ecuaciones lineales y su resolución matricial son la base matemática de muchos algoritmos de Machine Learning.


    Ecuaciones Lineales con Python

    Python hace que resolver sistemas lineales sea fácil y rápido con NumPy. Vamos a hacerlo de forma didáctica, con el mismo ejemplo de las frutas (dos ecuaciones, dos incógnitas), y luego generalizamos a más variables.

    Ve los artículos relacionados con las matrices en Python:

    El sistema del ejercicio de las frutas en formas matricial compacta se expreso como:

    $$A = \begin{bmatrix} 2 & 3 \\ 1 & 1 \end{bmatrix}, \vec{b} = \begin{bmatrix} 30 \\ 12 \end{bmatrix}$$

    Resolver el sistema con NumPy:

    import numpy as np
    
    # Definimos la matriz de coeficientes y el vector de resultados
    A = np.array([[2, 3],
                  [1, 1]])
    
    b = np.array([30, 12])
    
    # Resolver el sistema A x = b
    x = np.linalg.solve(A, b)
    
    print("Solución (x, y):", x)
    Solución (x, y): [6. 6.]

    Comprobar el resultado:

    # Verificamos A @ x = b
    print("Comprobación:", A @ x)
    Comprobación: [30. 12.]

    Usando la inversa de la matriz (método alternativo)

    Este método no se recomienda en práctica cuando hay muchas variables, porque calcular la inversa directamente es más costoso y menos estable numéricamente.

    A_inv = np.linalg.inv(A)
    x_alt = A_inv @ b
    
    print("Solución con A^-1:", x_alt)
    Solución con A^-1: [6. 6.]
  • PropTech Analytics: Apartamentos España 2019

    PropTech Analytics: Apartamentos España 2019

    El sector inmobiliario global está experimentando una transformación estructural impulsada por el fenómeno PropTech (Property Technology), donde la analítica de datos avanzada y el Big Data sustituyen a los métodos tradicionales de tasación y análisis de mercado. Hoy en día, plataformas líderes como Idealista o Zillow operan como masivos agregadores de información en tiempo real, abriendo una ventana de oportunidad única para la toma de decisiones basada en datos (Data-Driven Decisions). En este contexto, la capacidad de procesar, limpiar y modelar datos extraídos directamente de la web no es solo una ventaja competitiva, sino el estándar operativo para inversores institucionales, desarrolladores urbanos y analistas financieros en mercados altamente dinámicos.

    Data Science Pipeline 

    1. Ingesta de datos tabulares: Ejecutar el pipeline de lectura de fuentes de datos estructuradas en texto plano (raw data) para su inicialización en memoria.
    2. Curación y limpieza de datos (Data Wrangling / Preprocessing): Aplicar transformaciones en el DataFrame (imputación de valores nulos, parsing de tipos de datos, manejo de outliers y deduplicación) para optimizar la calidad de los datos (data quality) y mitigar sesgos en el modelado.
    3. Geocodificación y Enriquecimiento de Features: Implementar el proceso de geocoding mediante la API de Geopy para transmutar variables de texto (direcciones físicas) en vectores geoespaciales (latitud y longitud), permitiendo la representación cartográfica en un mapa interactivo.
    4. Análisis Exploratorio de Datos (EDA): examinar el conjunto de datos para entender sus características, detectar anomalías y descubrir patrones mediante resúmenes estadísticos y gráficos.
    5. Visualización de Analíticas Geoespaciales: Desplegar mapas de calor (heatmaps) o mapas coropléticos para mapear la distribución espacial e identificar sesgos geográficos o gradientes de precio entre regiones.
    6. Ingeniería de Características y Análisis de Correlación: Evaluar la covarianza y el impacto estadístico (feature importance) de las variables independientes del inmueble sobre la variable objetivo (target), que es el precio.
    7. Clustering para Segmentación de Mercado: Implementar algoritmos de aprendizaje no supervisado (como K-Means o DBSCAN) para agrupar patrones ocultos, reduciendo la dimensionalidad para perfilar clústeres del sector inmobiliario.
    8. Inferencia Estadística y Pruebas A/B (A/B Testing): Ejecutar tests estadísticos (como ANOVA, T-Test o pruebas no paramétricas) para validar la significancia estadística de las diferencias de precio e aislar el efecto de features específicas.
    9. Despliegue de un Dashboard de BI en Tableau: Desarrollar un cuadro de mando interactivo para habilitar el drill-down de métricas clave y permitir la exploración dinámica del dataset por parte de los stakeholders.
    10. Data Storytelling y Data-Driven Insights: Comunicar los hallazgos críticos del pipeline analítico mediante narrativas de datos, transformando métricas técnicas en recomendaciones estratégicas e insights accionables para el negocio.

    Página del proyecto en GitHub:

    https://github.com/fer78/Data-Analytics-Final-Portfolio-Project.git

    1. Introducción y Contexto del Negocio (Business Understanding)

    Proyecto Capstone del Curso Data Science: Analytics Specialist, de Codecademy. En este se desarrolla un Pipeline de Ciencia de Datos de extremo a extremo aplicado al sector PropTech (tecnología inmobiliaria). Para este análisis se ha seleccionado el Spanish Housing Dataset, un conjunto de datos reales de código abierto alojado en Kaggle. Los datos fueron recolectados originalmente mediante técnicas de web scraping automatizado sobre la plataforma  Idealista S.A.U., el portal inmobiliario líder en España.

    La investigación se enfoca estratégicamente en el segmento de apartamentos (apartments/condos) dentro del territorio español. Este subsector representa una categoría crítica en los núcleos urbanos y suburbanos de alta densidad, donde la demanda de soluciones habitacionales eficientes, accesibles y con alta liquidez es elevada.

    El propósito central de este análisis es desentrañar las dinámicas subyacentes del mercado inmobiliario español, aislando las características clave (features) que impactan directamente en la tasación y la elasticidad del precio. A través de un riguroso Análisis Exploratorio de Datos (EDA), estadística descriptiva e inferencial, se identifican patrones ocultos, asimetrías de precios y agrupaciones geoespaciales (clusters). Los resultados proveen insights de alto valor estratégico para tomadores de decisiones, inversores institucionales (REITs) y compradores privados internacionales.

    Nota metodológica: Con el fin de garantizar la escalabilidad del proyecto, la fase de curación y preprocesamiento de datos (Data Wrangling) se ejecuta de manera agnóstica sobre el volumen total del dataset. Esto permite estructurar una base de datos limpia, robusta y optimizada para futuros análisis predictivos o modelos de Machine Learning aplicados a otros tipos de activos (como viviendas unifamiliares o locales comerciales).

    2. Objetivos Estratégicos

    El objetivo principal de este proyecto es modelar y analizar el comportamiento estadístico de los apartamentos y viviendas unifamiliares en venta a lo largo de diversas provincias españolas durante el ejercicio fiscal 2019.

    Los objetivos específicos del pipeline analítico incluyen:

    • Ingesta y Curación de Datos: Diseñar un flujo de preprocesamiento robusto en Pandas para mitigar el ruido estadístico (outliers, nulos y duplicados).
    • Enriquecimiento Geoespacial: Implementar algoritmos de geocoding mediante la API de Geopy para transmutar direcciones textuales en vectores tridimensionales (latitud, longitud y altitud) que permitan una cartografía interactiva precisa.
    • Segmentación Avanzada: Aplicar modelos de aprendizaje no supervisado (Clustering) para clasificar el mercado e identificar micronichos de inversión.
    • Business Intelligence (BI): Construir e implementar un dashboard interactivo en Tableau enfocado en la exploración dinámica y el desglose (drill-down) de métricas macroeconómicas locales.
    • Localización Internacional: Adaptar la terminología técnica, métricas superficiales (de metros cuadrados a square feet) y formatos financieros al contexto normativo y cultural de los inversores privados de Estados Unidos (EE. UU.), facilitando la transferencia de conocimiento (Data Storytelling).

    3. Fuente, Arquitectura y Estructura de los Datos

    La fuente de datos de partida consiste en un dataset crudo de texto plano estructurado que consta de 100,000 registros (instancias) y 41 variables (características). La granularidad de la información abarca atributos multidimensionales de los listados inmobiliarios activos en el portal, agrupados de la siguiente forma:

    • Métricas Financieras y de Dimensión: Variable objetivo (target) precio, coste por unidad de superficie, tamaño del inmueble, entre otros.
    • Atributos Estructurales y de Calidad: Estado de conservación (renovado, a reformar), año de construcción, planta/piso.
    • Variables de Confort (Features Binarias): Presencia de sistemas de climatización (A/C), zonas verdes (jardín), terrazas, plazas de garaje y piscinas comunitarias o privadas.
    • Datos de Localización: Direcciones normalizadas, municipios, códigos postales y provincias.

    El conjunto de datos presenta una naturaleza híbrida compuesta por variables cuantitativas (discretas y continuas) y cualitativas (nominales y ordinales), ofreciendo un entorno óptimo para la inferencia estadística robusta y la ingeniería de características.

    4. Inspección Inicial del Dataset (Raw Data Snapshot)

    Para validar la integridad estructural e iniciar el proceso de auditoría de datos (Data Profiling), se presenta a continuación una muestra del primer registro indexado en memoria dentro de nuestro DataFrame original:

    print(raw_data.head(1).T)
                                                                                   0
    ad_description                 Precio chalet individual en la localidad de Ab...
    ad_last_update                                Anuncio actualizado el 27 de marzo
    air_conditioner                                                                0
    balcony                                                                        0
    bath_num                                                                       2
    built_in_wardrobe                                                              0
    chimney                                                                        0
    condition                                               segunda mano/buen estado
    construct_date                                                               NaN
    energetic_certif                                                             NaN
    floor                                                                  2 plantas
    garage                                     plaza de garaje incluida en el precio
    garden                                                                         1
    ground_size                                                                  NaN
    heating                                                                      NaN
    house_id                                                                81717634
    house_type                                           Casa o chalet independiente
    kitchen                                                                      NaN
    lift                                                                         NaN
    loc_city                                                             Urcabustaiz
    loc_district                                                          La iglesia
    loc_full                                 La iglesia , Urcabustaiz , Zuya, Álava 
    loc_neigh                                                                    NaN
    loc_street                                                                   NaN
    loc_zone                                                             Zuya, Álava
    m2_real                                                                     1000
    m2_useful                                                                  172.0
    obtention_date                                                        2019-03-29
    orientation                                              norte, sur, este, oeste
    price                                                                     310000
    reduced_mobility                                                               0
    room_num                                                                       4
    storage_room                                                                   0
    swimming_pool                                                                  0
    terrace                                                                        1
    unfurnished                                                                  NaN
    number_of_companies_prov                                                   19147
    population_prov                                                           328868
    companies_prov_vs_national_%                                                0.57
    population_prov_vs_national_%                                               0.70
    renta_media_prov                                                        19889.00

    5. Pipeline de Procesamiento y Curación de Datos (Data Wrangling)

    El proceso de preparación y adecuación del dataset se estructuró en un pipeline secuencial dividido en tres fases fundamentales, garantizando así la calidad de los datos (Data Quality), la consistencia interna y la reproducibilidad del análisis.

    Fase 1: Preprocesamiento y Depuración Estructural (Initial Transformation)

    El objetivo de esta primera fase fue mitigar el ruido estadístico inicial, descartar redundancias en el flujo de datos y homogeneizar los formatos vectoriales necesarios para las posteriores tareas de enriquecimiento geoespacial. Las operaciones críticas ejecutadas incluyeron:

    • Filtrado de Características (Feature Dropping / Data Filtering): Se realizó un análisis de relevancia para identificar y remover 16 variables que no aportaban valor predictivo ni descriptivo al núcleo del negocio (como identificadores internos del portal web o metadatos de los anuncios). Esta reducción de dimensionalidad optimizó drásticamente el consumo de memoria en el entorno de ejecución.
    • Deduplicación de Instancias (Data Deduplication): Se auditó el DataFrame en busca de registros idénticos que pudieran sesgar las distribuciones de precios (causados habitualmente por la republicación de anuncios). Se identificaron e indexaron 6,071 registros duplicados, los cuales fueron eliminados por completo para asegurar la unicidad de las observaciones.
    • Tratamiento de Valores Omisos (Handling Missing Data): Se evaluó la matriz de densidad de nulos para determinar el mecanismo de pérdida de información (MCAR, MAR o MNAR). Dependiendo de la variable, se aplicaron estrategias diferenciadas:
      • Filtrado por umbral (Drop) en variables críticas de localización imposibles de inferir.
      • Imputación estadística (empleando la mediana del vecindario/provincia) para variables numéricas continuas como la superficie o el precio.
      • Categorización explícita (como “No especificado”) para atributos cualitativos binarios o nominales, evitando así la pérdida de registros valiosos.
    missing_values = raw_data.isnull().sum().sort_values(ascending=False)
    print(missing_values[missing_values > 0])
    ground_size       93928
    kitchen           91902
    loc_street        80147
    heating           69857
    construct_date    63150
    orientation       56789
    garage            56130
    loc_neigh         52086
    m2_useful         44501
    lift              38965
    condition         13295
    dtype: int64
    • Imputación por Ausencia Estructural (Structural Missingness):
      Se identificó que los valores faltantes en ciertas variables cualitativas binarias (como la disponibilidad de garaje o ascensor) no respondían a una pérdida aleatoria de información, sino a una omisión estructural. En el sector PropTech, la ausencia de registro equivale a la inexistencia del atributo. Por lo tanto, se ejecutó una imputación determinista reemplazando estos nulos por el valor binario 0 (Falso).
    • Filtrado por Umbral de Densidad (Sparsity Filtering):
      Se auditó la tasa de completitud de todas las características. Nueve variables que exhibían un índice de valores ausentes superior al 60% fueron descartadas de forma definitiva, mitigando el riesgo de introducir sesgos artificiales mediante técnicas de imputación masiva sobre matrices dispersas.

    Fase 2: Armonización de Variables y Derivación de Características (Feature Engineering)

    Con el fin de estandarizar el dataset e iniciar el proceso de auditoría y perfilado de variables (Data Profiling), se implementaron las siguientes operaciones a nivel de registro:

    • Estandarización de Categorías y Localización de Dominio: Para adaptar el proyecto al mercado objetivo de inversores de EE. UU., se transformó la taxonomía y codificación original hacia la jerga inmobiliaria americana (e.g., convirtiendo tipos de propiedad a Apartment/CondoSingle-Family Home, etc.). Asimismo, se corrigieron inconsistencias sintácticas y tipográficas presentes en el texto libre.
    • Casteo de Tipos de Datos (Type Casting): Se reasignaron los tipos de datos en memoria para optimizar el rendimiento del sistema, forzando variables numéricas mal indexadas a flotantes o enteros (float64/int64), y convirtiendo variables de texto repetitivas en el tipo eficiente category de Pandas.
    • Normalización de Texto para Geocodificación: Se aplicaron expresiones regulares (Regex) para limpiar la variable de dirección física, eliminando ruidos de texto y prefijos redundantes (como “Calle”, “Avenida”, “Av.”) que disminuyen la precisión de los motores de búsqueda geográfica.
    • Derivación de Características de Respaldo (Feature Derivation): Se diseñó una variable sintética denominada city_prov mediante la concatenación de los campos loc_city y loc_zone. Esta variable actúa como una directiva de ubicación secundaria (fallback location) en el pipeline, asegurando que si la dirección específica falla al geocodificarse, el sistema pueda aproximar el registro a nivel municipal.
    • Persistencia Intermedia: El DataFrame limpio y armonizado se exportó a un nuevo archivo serializado, garantizando un punto de restauración óptimo antes de iniciar la fase de cómputo intensivo.

    6. Enriquecimiento Geoespacial y Procesamiento por Lotes (Batch Geocoding)

    Para transformar las direcciones físicas en vectores de coordenadas espaciales (Latitud y Longitud), se integró la librería Geopy utilizando el servicio de geocodificación Nominatim, un motor de código abierto basado en el ecosistema de mapas vectoriales OpenStreetMap.

    Arquitectura del Pipeline de Geocodificación por Bloques (Chunking)

    Debido al volumen masivo del dataset (100,000 registros), realizar peticiones síncronas a una API externa en un solo bloque comprometería la memoria del sistema y provocaría el bloqueo por tiempo de espera (timeout). Para solucionar esta limitación de infraestructura, se diseñó una arquitectura de procesamiento por lotes (batch processing) dividiendo el DataFrame en bloques (chunks) de 10,000 registros.

    El flujo algorítmico se estructuró a través del siguiente pipeline de funciones:

    [Dataset Original] ──> (create_chunks) ──> [Bloques de 10k en Disco]
                                                        
                 ┌──────────────────────────────────────┘
                 
          (process_chunk) ──> Loop Fila por Fila > (geolocate) ──> (split_address)
                 
                 
         [Liberación Memoria] ──> [Fusión Final de Chunks] > [Dataset Geoespacial]
    
    • create_chunks: Segmenta el DataFrame maestro en particiones homogéneas de 10,000 filas y persiste temporalmente cada bloque en disco para minimizar la huella de memoria RAM.
    • geolocate: Invoca el motor de Nominatim fila por fila dentro del bloque para capturar las coordenadas y retornar una cadena de texto con la dirección normalizada completa encontrada por el servidor.
    • split_address: Realiza un proceso de parsing (análisis sintáctico) sobre la dirección completa devuelta por el servidor para extraer y estructurar vectorialmente variables críticas: código postal (ZIP code), municipio y región.
    • process_chunk: Actúa como la función orquestadora del lote. Ejecuta secuencialmente  geolocate y split_address, integra las nuevas características geoespaciales en el bloque actual, escribe el resultado parcial en almacenamiento físico y ejecuta el recolector de basura de Python para liberar la memoria antes de procesar el siguiente lote.

    Finalmente, un script de consolidación unificó todos los bloques procesados en un único dataset maestro enriquecido.

    Optimización Visual mediante Dispersión de Coordenadas (Spatial Jittering)

    Durante la fase de control de calidad y representación cartográfica preliminar, se detectó una alta colisión de registros en coordenadas idénticas. Este fenómeno de superposición espacial responde a tres dinámicas del mercado real:

    1. Unidades Multifamiliares: Propiedades verticales (apartamentos) que coexisten dentro del mismo edificio físico.
    2. Geocodificación por Fallback: Registros cuya dirección original presentaba fallos sintácticos graves, forzando al pipeline a utilizar la variable de respaldo city_prov, ubicando la propiedad en el centroide geográfico de la ciudad.
    3. Anuncios Ciego (Blind Listings): Una práctica comercial extendida en el sector Real Estate donde las agencias omiten deliberadamente la dirección exacta para proteger la privacidad del vendedor, evitar la desintermediación y prevenir que competidores contacten directamente al propietario. Estos anuncios comparten coordenadas genéricas centralizadas.

    Implementación del Algoritmo de Jittering

    Para resolver la superposición visual en los mapas interactivos y permitir un análisis de densidad correcto, se aplicó la técnica estadística de Jittering Spatial, la cual introduce ruido estocástico aleatorio de baja magnitud a las coordenadas duplicadas.

    El sub-pipeline matemático opera mediante dos funciones clave:

    • move_coordinates: Desplaza de forma vectorial las coordenadas originales calculando un nuevo punto a partir de un ángulo de azimut y una distancia radial aleatoria. Estos valores métricos se transmutan a grados de arco geográfico (ajustando la deformación por latitud) y se adicionan a los vectores originales.
      (Nota de limitación del modelo: Al aplicar ruido aleatorio en zonas costeras, existe un margen de error donde algunos registros pueden sufrir un desplazamiento infinitesimal que los posicione visualmente sobre la superficie marina).
    • disperse_coordinates: Actúa como la función de agrupación. Identifica mediante una operación de agregación todas las coordenadas duplicadas en el dataset y aplica de manera aislada la función move_coordinates a cada registro repetido, distribuyendo las propiedades de forma concéntrica en un radio controlado por parámetros de distancia mínima y máxima predefinidos.

    Muestra Visual del Impacto del Algoritmo (Spatial Jittering Demo)

    A continuación, se ilustra el comportamiento del algoritmo donde múltiples instancias colapsadas en un único centroide se transforman en una distribución dispersa y legible para el analista o el usuario final:

    Curación de Datos Avanzada y Acotación del Espacio Muestral (Data Cleaning for Analytics)

    Una vez integrado el algoritmo de jittering, el dataset se exportó como un punto de control intermedio. En esta etapa, el DataFrame maestro consolidó un volumen de 89,948 registros y 19 columnas  (incluyendo las 6 nuevas variables vectoriales derivadas de la fase de geocodificación).

    processed_data.info()
    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 89948 entries, 0 to 89947
    Data columns (total 19 columns):
     #   Column           Non-Null Count  Dtype  
    ---  ------           --------------  -----  
     0   air_conditioner  89948 non-null  int64  
     1   bath_num         89948 non-null  int64  
     2   chimney          89948 non-null  int64  
     3   condition        89948 non-null  object 
     4   garage           89948 non-null  object 
     5   garden           89948 non-null  int64  
     6   house_type       89948 non-null  object 
     7   m2_real          89948 non-null  int64  
     8   price            89948 non-null  float64
     9   room_num         89948 non-null  int64  
     10  storage_room     89948 non-null  int64  
     11  swimming_pool    89948 non-null  int64  
     12  terrace          89948 non-null  int64  
     13  latitude         89948 non-null  float64
     14  longitude        89948 non-null  float64
     15  address          89948 non-null  object 
     16  p_code           89948 non-null  int64  
     17  region           89948 non-null  object 
     18  municipality     89948 non-null  object 
    dtypes: float64(3), int64(10), object(6)
    memory usage: 13.0+ MB

    A partir de esta estructura, se diseñó un pipeline de depuración quirúrgica para asegurar la validez estadística, eliminando sesgos geográficos y comerciales antes de la fase de modelado analítico:

    • Validación de Límites Geoespaciales (Bounding Box Filtering): Para evitar errores de proyección en la cartografía, se realizó una auditoría de coordenadas aplicando máscaras booleanas basadas en el bounding box oficial del territorio español:
      • Latitud27.6ºN, 43.8ºN (Desde el archipiélago canario hasta el litoral cantábrico).
      • Longitud: -18.2ºW, 4.3ºE  (Desde la isla de El Hierro hasta la costa oriental de Baleares).
      Esta validación identificó 37 anomalías espaciales (outliers geográficos), las cuales fueron removidas del flujo principal para evitar distorsiones en los mapas interactivos.
    • Filtrado por Representatividad Muestral: Con el objetivo de estabilizar la varianza del modelo, se ejecutó una poda estadística en variables categóricas de baja frecuencia:
      • Se removieron regiones administrativas con un volumen de registros estadísticamente insignificante (low-density regions).
      • Se descartaron tipologías de vivienda con nula representatividad en el mercado masivo urbano (tales como castillos, palacios, ranchos, mansiones, casas torres y casas rurales), concentrando el espectro analítico puramente en el segmento residencial estándar.
    Código de la gráfica
    fig, ax = plt.subplots(2,1, figsize=(10, 4))
    
    sns.boxplot(x=processed_data['latitude'], ax=ax[0])
    ax[0].set_title('Latitude Range')
    
    sns.boxplot(x=processed_data['longitude'], ax=ax[1])
    ax[1].set_title('Longitude Range')
    
    fig.suptitle('Coordinate Ranges', fontsize=14)
    plt.tight_layout()
    plt.show()

    • Ingeniería de Características (Feature Binning & Binning Stratification): Se transformaron variables continuas en estructuras categóricas ordinales para facilitar la segmentación de mercado en Tableau:
      • price_segment: Clasificación del inventario según su valor financiero:
        • Affordable
        • Mid-Range
        • Luxury
      • size_category: Clasificación por densidad de superficie construida (mapeada bajo estándares internacionales de la industria):
        • Small ()
        • Medium
        • Large ()
    • Tratamiento de Inconsistencias Lógicas: Se ejecutó un filtro de integridad física eliminando registros con valores imposibles o nulos en variables clave de habitabilidad, tales como propiedades con cero baños o cero habitaciones.
    • Truncamiento del Espectro Inmobiliario (Capping Extremes): Al evaluar la función de densidad de probabilidad (PDF) de la variable objetivo price, se observó una cola pesada hacia la derecha (right-skewed distribution). Para mitigar el efecto de datos atípicos o errores de digitación en el portal inmobiliario, se parametrizó un umbral de corte estricto, aislando el análisis entre un mínimo de €10,000 y un máximo de €2,000,000. Cualquier registro fuera de este intervalo operativo fue removido.

    Algoritmo de Remoción de Outliers Segmentado (Stratified Outlier Treatment)

    Eliminar valores atípicos de forma global sobre un mercado tan heterogéneo como el inmobiliario introduce un sesgo metodológico crítico: un precio “atípico alto” para un apartamento pequeño en una región rural podría ser un precio “atípico bajo” para un inmueble en una zona de lujo urbana.

    Para resolver esto, se desarrolló e implementó un enfoque de remoción adaptativa y estratificada mediante dos funciones customizadas en Python:

    1. remove_outliers: Función atómica que calcula el Rango Intercuartílico () sobre una serie numérica. Define las barreras de aceptación estadística mediante los límites inferior y superior tradicionales:
      Cualquier observación que se posicione fuera de estas fronteras analíticas es clasificada como un outlier estadístico y removida.
    2. clean_outliers_by_segment: Función orquestadora que aplica una estrategia de descomposición jerárquica mediante agrupamientos sucesivos (nested group-by). El algoritmo aísla el cálculo del IQR de forma justa y comparable, subdividiendo el conjunto de datos bajo el siguiente flujo: 
    [Dataset Consolidado]
       
       └──> 1. Estratificación por Segmento de Precio (`price_segment`)
                   
                   └──> 2. Estratificación por Tipología de Vivienda (`property_type`)
                               
                               └──> 3. Estratificación por Región (`region`)
                                           
                                           └──> [Aplicación del IQR local]
    

    Esta normalización multicapa garantiza que los valores considerados atípicos se evalúen respetando el comportamiento de sus pares directos de mercado, preservando la microestructura económica del conjunto de datos.

    Consolidación del Dataset Final para Análisis

    Tras la ejecución completa de este pipeline de ingeniería y curación de datos, la dimensión final del DataFrame maestro se estabilizó en 77,677 registros y 21 columnas. Este volumen de datos limpio, curado, enriquecido y libre de ruido estadístico conforma la base de datos de alta fidelidad (Analytics-Ready Dataset) utilizada para las posteriores fases de analítica inferencial y visualización.

    Para verificar la disposición física de la estructura de datos en memoria lista para su ingesta en Tableau, se presenta un perfil transpuesto del primer registro procesado:

    print(spain_housing.head(1).T)
    air_conditioner                                                  0
    bath_num                                                         2
    chimney                                                          0
    condition                                                   Resale
    garage                                                Not Included
    garden                                                           1
    house_type                                      Single-Family Home
    m2_real                                                        275
    price                                                    242000.00
    room_num                                                         3
    storage_room                                                     1
    swimming_pool                                                    1
    terrace                                                          1
    latitude                                                     38.59
    longitude                                                    -0.14
    address          Urbanizatzación Convent de les Monges / Urbani...
    p_code                                                        3530
    region                                        Comunidad Valenciana
    municipality                                              Alicante
    price_segment                                           Affordable
    size_category                                                Large
    

    Análisis Exploratorio de Datos (EDA) y Modularización Analítica

    Con el conjunto de datos limpio y validado estadísticamente, se procedió a la fase de Análisis Exploratorio de Datos (EDA). En este punto, la investigación se estructuró de manera estratificada por cada price_segment, aislando el comportamiento de las variables continuas y categóricas para identificar dinámicas específicas de oferta y demanda.

    Arquitectura de Software: Modularización mediante functions.py

    Para garantizar la mantenibilidad, escalabilidad y legibilidad del código (siguiendo las mejores prácticas de ingeniería de software para Ciencia de Datos), se evitó saturar el cuaderno principal (Jupyter Notebook) con bloques de código redundantes de generación de gráficos. En su lugar, se encapsuló toda la lógica visual en un script modular independiente denominado functions.py.

    Este fichero actúa como una librería interna que es importada en el entorno de ejecución, permitiendo invocar funciones dinámicas y parametrizables de manera limpia:

    Catálogo de Funciones de Abstracción Analítica

    Las funciones integradas en el pipeline modular se dividen según su propósito específico dentro de la auditoría analítica:

    1. Motores de Transformación e Interrogación de Datos

    • filterdf(df, col1, val1, col2, val2): Retorna un sub-DataFrame ejecutando una máscara booleana bidimensional basada en dos características y sus respectivos umbrales operativos.

    2. Motores de Análisis Univariado y Distribución

    • boxplot_view(dataframe, column): Despliega diagramas de caja para diagnosticar la asimetría y el rango intercuartílico de variables continuas.
    • boxplot_view_wo(dataframe, column): Muestra la misma distribución de cajas, pero truncando los extremos (whiskers) para aislar visualmente los datos atípicos y mejorar el detalle de los cuartiles centrales.
    • distribution_views(dataframe): Inicializa una cuadrícula de gráficos de densidad para contrastar la dispersión en los campos críticos m2_real y price.
    • plot_histogram(df, column, bins=20, kde=True, xlim=None): Genera histogramas avanzados con la estimación de densidad de kernel (KDE) integrada para evaluar la normalidad de la variable.

    3. Motores de Análisis Categórico y Frecuencias

    • binary_categorical_view(dataframe): Evalúa simultáneamente el volumen y tasa de penetración de características booleanas ligadas al confort habitacional (air_conditionerchimneygardenstorage_roomswimming_poolterrace).
    • categorical_features_view(dataframe): Desglosa las variables categóricas ordinales y cardinales del inventario como room_numbath_num y el estado general (condition).
    • plot_rooms_bathrooms_distribution(df): Muestra la densidad de la distribución cruzada de dormitorios y cuartos de baño específicos para un nicho analítico.
    • plot_category_histograms(df, numeric_col, category_col): Superpone histogramas de variables cuantitativas segregados por etiquetas de una dimensión cualitativa.

    4. Motores de Análisis Bivariado, Multivariado y Correlación

    • bivariate_distribution(dataframe, group_col, target_col, show_outliers): Acopla diagramas de caja cruzados junto a una matriz de salida de estadística descriptiva (media, mediana, desviación estándar) para analizar la variabilidad de una métrica frente a factores grupales.
    • plot_binary_categorical_relationships(dataframe, target_variable): Ejecuta un análisis de contraste que mapea el impacto de cada atributo binario sobre una variable continua (como el precio), inyectando una tabla resumen con los deltas de variación.
    • correlation_heatmap_by_size_category(df): Calcula y grafica matrices de correlación de Pearson o Spearman segregadas de forma independiente para cada nivel de size_category.
    • plot_distribution_by_price_segment(df): Ejecuta un cruce multidimensional agrupando por segmento financiero y tipología de activo para proyectar la densidad de la oferta mediante un mapa de calor bidimensional.

    Muestra de implementación: functions.py (Script Snippet)

    A continuación se expone, a modo de ejemplo de ingeniería de código, la arquitectura interna de una de las funciones clave del módulo. Esta estructura destaca por su manejo integrado de visualizaciones con Seaborn/Matplotlib y la inyección automática de resúmenes de datos numéricos en la consola:

    def bivariate_distribution(dataframe, group_col, target_col, show_outliers=True, figsize=(10, 6)):
        """
        Displays a boxplot and a summary table of a variable grouped by another variable's values.
        """
        df_copy = dataframe.copy()
    
        # Boxplot
        plt.figure(figsize=figsize)
        ax = sns.boxplot(data=df_copy, x=group_col, y=target_col, showfliers=show_outliers, palette="pastel")
        plt.title(f'Boxplot of {target_col} by {group_col} with Mean Values')
        plt.xlabel(group_col)
        plt.ylabel(target_col)
        plt.xticks(rotation=45)
        plt.show()
    
        # Summary Statistics table
        summary_stats = df_copy.groupby(group_col)[target_col].agg(
            mean=lambda x: round(x.mean(), 2),
            Q1=lambda x: x.quantile(0.25),
            Q3=lambda x: x.quantile(0.75),
            std_dev=lambda x: round(x.std(), 2)
        ).reset_index()
        summary_stats = summary_stats.sort_values(by='mean', ascending=False).reset_index(drop=True)
        print(f"Summary Table of {target_col} by {group_col} sorted by Mean:")
        print(summary_stats)
    bivariate_distribution(affordable_apartments, 'region', 'price', show_outliers=False)
    Summary Table of price by region sorted by Mean:
                     region      mean        Q1        Q3  std_dev
    0        Islas Baleares 197767.25 155000.00 240000.00 56301.50
    1   Comunidad de Madrid 180755.40 133350.00 229000.00 59592.77
    2            País Vasco 176976.07 133000.00 220794.00 60137.55
    3              Cataluña 133926.13  96000.00 168000.00 50869.32
    4               Galicia 116780.80  77000.00 140000.00 55973.88
    5              Canarias 114996.06  85000.00 136000.00 41459.24
    6       Castilla y León 108825.89  69000.00 140000.00 53845.32
    7             Andalucía 104710.97  61650.00 141650.00 54689.41
    8  Comunidad Valenciana 100787.91  59000.00 126800.00 58180.42
    9    Castilla-La Mancha  94720.85  58555.00 120000.00 50163.13

    Hallazgos Analíticos y Evidencia Empírica (Exploratory Insights)

    A lo largo de cada sección del análisis de datos se documentaron detalladamente las métricas clave descubiertas y las distribuciones de frecuencia de las variables del entorno PropTech. El reporte analítico exhaustivo, junto con los gráficos de dispersión y mapas de calor interactivos generados en esta etapa, se encuentra completamente documentado y disponible para su consulta en el repositorio oficial del proyecto en GitHub.

    Inferencia Estadística y Modelado Predictivo (Advanced Analytics)

    En esta fase del pipeline, se transicionó de la analítica descriptiva a la analítica diagnóstica y predictiva. Se aplicaron metodologías de estadística inferencial y modelos lineales avanzados para validar con rigor matemático las correlaciones y patrones observados durante el EDA, buscando dar respuesta a la pregunta de negocio central: ¿Cuáles son los inductores de valor (value drivers) estadísticamente significativos en la tasación del mercado de apartamentos en España?

    Este bloque de analítica avanzada se articuló bajo dos verticales metodológicas:

    1. Inferencia Estadística (Pruebas de Hipótesis): Diseñada para mitigar el riesgo de sesgo por aleatoriedad y confirmar la significancia de las relaciones.
    2. Modelado Predictivo Supervizado: Orientado a cuantificar el poder explicativo y la elasticidad de los vectores geográficos sobre la variable objetivo (target).

    Validaciones Estadísticas e Inferencia

    1. Análisis de Varianza (ANOVA) para Segmentos de Superficie (size_category)

    Se ejecutó un test ANOVA de una vía (One-Way ANOVA) para contrastar si las discrepancias de precio observadas entre los grupos de tamaño (SmallMediumLarge) eran producto del azar o respondían a dinámicas estructurales de mercado:

    • Hipótesis Nula () (No existen diferencias significativas entre los precios medios de las tres categorías).
    • Hipótesis Alternativa (): Al menos un par de medias poblacionales difiere significativamente entre sí.
    • Resultado: El rechazo de la hipótesis nula () confirmó que la escala métrica de la vivienda fragmenta el mercado en estratos de valoración completamente independientes.

    2. Evaluación del Impacto del Estado de Conservación (condition) en el Precio

    Para determinar si el ciclo de depreciación física o la prima por estreno impactan la valoración de forma homogénea, se estructuró un segundo diseño ANOVA comparando los precios según el estado de preservación indexado en el portal:

    • Grupos de ContrasteNew construction (Nueva), Good condition (Reventa) y To renovate (Necesita reforma).
    • Resultado: La prueba arrojó significancia estadística crítica, validando empíricamente que el coste de oportunidad de la reforma y el valor premium del suelo a estrenar son factores determinantes en la dispersión de precios.

    3. Análisis de Correlación de Pearson para Atributos de Habitabilidad (bath_num)

    Se evaluó la intensidad del vínculo lineal existente entre la densidad de cuartos de baño y el precio final de los apartamentos:

    • Hipótesis Nula () (No existe correlación lineal estadísticamente significativa entre el número de baños y el precio del inmueble).
    • Hipótesis Alternativa () (Existe una correlación lineal significativa entre ambas variables).
    • Resultado: Se evidenció una correlación lineal positiva y robusta, confirmando que la infraestructura interna de fontanería actúa como un proxy de lujo y confort habitacional fuertemente valorado por el mercado.

    Modelado Lineal Predictivo: El Vector Geográfico como Inductor de Valor

    Más allá de la validación de hipótesis aisladas, se construyó y entrenó un modelo de Regresión Lineal Múltiple. El objetivo de este algoritmo supervisado fue aislar el impacto puramente geoespacial, evaluando en qué medida los vectores tridimensionales combinados (latitud, longitud) y las variables categóricas regionales explican estadísticamente la varianza de la variable dependiente price.

    Este modelo base (baseline model) cuantifica el impacto marginal de la ubicación geográfica exacta, sentando los cimientos matemáticos para algoritmos más complejos de tasación automatizada (AVM – Automated Valuation Models).

    Impacto del Proyecto y Aplicación de Negocio (Business Value)

    Al integrar la exploración visual, la inferencia estadística y el modelado predictivo, el proyecto transita con éxito desde la descripción analítica hacia la anticipación del comportamiento del mercado. Este marco de trabajo robusto se traduce en una toma de decisiones informada por datos (Data-Driven Decisions) con aplicaciones críticas para diversos stakeholders de la industria:

    • Agentes y Brókers Inmobiliarios: Optimiza las estrategias de fijación de precios de salida (listing price) basándose en el comportamiento real de las features del entorno.
    • Inversores Corporativos y Compradores Privados: Permite identificar anomalías del mercado, micronichos de inversión de alto rendimiento (yield) y activos infravalorados respecto a su entorno geoespacial.
    • Desarrolladores, Constructores y Arquitectos: Provee métricas claras sobre la configuración óptima de la vivienda (relación de tamaño, habitaciones y baños) más demandada y valorada en cada región.
    • Planificadores Urbanos y Oficinas de Desarrollo Económico: Aporta datos empíricos sobre la densidad de la oferta y la distribución del valor del suelo, esenciales para el diseño de políticas de vivienda y zonificación urbana.

    Visualización Interactiva y Business Intelligence (Tableau Dashboard)

    Para democratizar el acceso a los insights y permitir que los stakeholders no técnicos exploren los resultados de manera autónoma, los datos curados fueron exportados e integrados en un cuadro de mando interactivo desarrollado en Tableau.

    El diseño del dashboard se estructuró bajo los siguientes pilares de Experiencia de Usuario (UX) y Analítica Visual:

    • Exploración Dinámica mediante Filtros en Cascada: Permite al usuario aislar el mercado de forma interactiva seleccionando el price_segment, la región geográfica o la tipología específica de la vivienda.
    • Mapeo de Densidad Geoespacial: Utiliza las capas vectoriales enriquecidas en la fase de geocodificación para proyectar mapas de calor y clústeres visuales, permitiendo identificar zonas calientes (hotspots) de precios en tiempo real.
    • Métricas Macroeconómicas Locales: Cuadros de mando (KPI Cards) que calculan automáticamente el precio medio por metro cuadrado (y su equivalencia a square feet para el mercado de EE. UU.), la mediana de habitaciones y los ratios de disponibilidad por provincia.

    Conclusiones y Recomendaciones del Pipeline Analítico (Data-Driven Insights)

    Tras completar el pipeline analítico, validar las pruebas inferenciales y ajustar el modelo de regresión sobre el segmento de apartamentos en España, se sintetizan las siguientes conclusiones fundamentales para el negocio (p. 1):

    1. Validación de los Inductores de Valor Físicos (Property Features)

    • El impacto crítico de la infraestructura interna: Las pruebas estadísticas rechazaron formalmente la hipótesis nula respecto a la distribución de baños (p-value = 0.0), demostrando una correlación positiva moderada (p=0.49) con el precio de venta. Esto confirma que la densidad de cuartos de baño es un proxy de confort habitacional que pondera más en el precio final que el número de habitaciones independientes, especialmente en los segmentos Medium y Large (p. 1).
    • Preeminencia del área construida: La matriz de correlaciones determinó que la superficie real (m2_real) mantiene el vínculo más fuerte con la variable objetivo precio (p=0.60). Asimismo, se validó mediante el test ANOVA (F-stat = 7878.25, p-value = 0.0) que la segmentación por tamaño (SmallMediumLarge) divide el mercado en estratos de valoración completamente independientes y significativos.

    2. Dinámicas de Conservación y Segmentación del Mercado

    • El paradigma de la Obra Nueva vs. Reventa: El test ANOVA enfocado en el estado de conservación (condition) ratificó la existencia de diferencias significativas en los precios medios. (F-stat = 17.64, p-value < 0.05) Sin embargo, el análisis descriptivo profundo reveló un comportamiento asimétrico según el poder adquisitivo: mientras que en el segmento Affordable la obra nueva lidera el precio premium, en el segmento Luxury las propiedades de reventa (resale) mantienen promedios superiores a €1M, sugiriendo que la ubicación prime de los activos consolidados supera el valor de depreciación física.
    • Asimetría Geográfica de la Oferta: El inventario inmobiliario de apartamentos está masivamente dominado por el segmento Affordable (79% del total de registros) y propiedades Small de hasta 93  (57%). Territorios como el País Vasco lideran el volumen absoluto de este mercado base, mientras que la oferta de los segmentos Mid-Range (16%) y Luxury (4%) está estrictamente polarizada y concentrada en tres núcleos: Islas Baleares, Comunidad de Madrid y País Vasco (p. 1).

    3. Diagnóstico del Modelo Predictivo Geoespacial (Spatial Regression)

    • Poder Explicativo de la Ubicación: El modelo de regresión lineal múltiple (OLS) parametrizado con variables puramente geográficas arrojó un R^2  ajustado de 0.192. Esto demuestra matemáticamente que la localización (coordenadas vectoriales y región) es capaz de explicar de forma aislada el 19.2% de la variabilidad total de los precios de los apartamentos en España.
    • Gradiente de Precios y Sesgo Regional: La regresión confirmó la influencia del eje Norte-Sur del país a través de la variable latitude, la cual posee un coeficiente positivo y altamente significativo. Asimismo, se identificó que la región de Canarias inyecta el mayor impacto positivo marginal en la tasación promedio , contrastando con penalizaciones significativas en la valoración media de regiones como Galicia o Cataluña tras ajustar por el resto de factores espaciales .
    • Limitaciones del Modelo Baseline: El elevado número de condiciones del modelo alerta sobre la existencia de multicolinealidad entre los predictores espaciales. Además, la falta de normalidad en la distribución de los residuos (confirmada por el test de Jarque-Bera) evidencia la necesidad de transicionar en futuras iteraciones hacia arquitecturas no lineales (como Random Forest Regressor o XGBoost) e incorporar las variables estructurales desestimadas (m2_real y bath_num) para elevar la robustez del ajuste predictivo.

    Recomendaciones Estratégicas para Stakeholders

    • Para Inversores Internacionales (EE. UU.): Las regiones de Castilla-La Mancha y Comunidad Valenciana presentan las oportunidades de arbitraje más eficientes en coste por unidad de superficie, ofreciendo apartamentos sustancialmente más amplios a tasas de cotización bajas. Por el contrario, Madrid y Cataluña representan mercados altamente competitivos y compactos con ratios elevados de precio por pie cuadrado.
    • Para Desarrolladores Urbanos: Dada la fuerte correlación de la variable bath_num con el precio de mercado, los proyectos de optimización de activos (house flipping o remodelaciones residenciales) deben priorizar la adición o mejora de un segundo o tercer cuarto de baño por encima de la subdivisión de dormitorios, maximizando el retorno de la inversión (ROI) por metro cuadrado.

    Stack Tecnológico y Entorno de Ejecución (Tech Stack)

    Para garantizar la reproducibilidad de este entorno de análisis, se detallan las tecnologías y librerías de Python utilizadas en el pipeline:

    • Manipulación y Core AnalíticoPython 3.xPandasNumPy.
    • Ingeniería GeoespacialGeopy (Motor OpenStreetMap/Nominatim).
    • Inferencia Estadística y ModeladoSciPy (módulo stats para ANOVA y Pearson), Statsmodels / Scikit-Learn (Regresión Lineal).
    • Visualización de Datos y BIMatplotlibSeabornTableau Desktop / Public.

    https://github.com/fer78/Data-Analytics-Final-Portfolio-Project.git

  • Fundamentos Matemáticos para la Ciencia de Datos

    Comprender los principios que sustentan el análisis y la inteligencia artificial

    En el ecosistema actual de la Ciencia de Datos, donde confluyen la estadística, la programación y el conocimiento del dominio, las matemáticas ocupan un lugar central. Son el lenguaje que permite describir, modelar y comprender los fenómenos que los datos representan.

    Sin una base matemática sólida, la práctica del análisis de datos corre el riesgo de reducirse a la mera aplicación mecánica de algoritmos, sin entender las razones detrás de sus resultados. Por el contrario, dominar los fundamentos matemáticos otorga al profesional la capacidad de interpretar, justificar y optimizar cada decisión analítica.

    El papel de las matemáticas en la ciencia de datos

    Las matemáticas no son un componente accesorio: constituyen el núcleo conceptual de la disciplina. Cada área del proceso analítico —desde la limpieza y representación de los datos hasta la modelización y evaluación de los resultados— se apoya en conceptos matemáticos esenciales:

    • El álgebra lineal estructura la información en forma de vectores y matrices, haciendo posible el procesamiento eficiente de grandes volúmenes de datos y el funcionamiento interno de algoritmos como la regresión o las redes neuronales.
    • El cálculo describe el cambio y la optimización; es la herramienta que permite ajustar los parámetros de un modelo hasta minimizar el error.
    • La probabilidad y la estadística ofrecen el marco teórico para inferir, predecir y tomar decisiones bajo incertidumbre.
    • La optimización formaliza la búsqueda de soluciones óptimas en espacios complejos, un principio fundamental en el aprendizaje automático.
    • La teoría de conjuntos y la lógica proporcionan el lenguaje formal para definir relaciones, categorías y condiciones sobre los datos.

    En conjunto, estos campos no solo explican el “cómo” de los algoritmos, sino el “por qué” de su funcionamiento y sus limitaciones.

    Objetivos de esta serie de artículos

    Esta serie de artículos tiene como propósito presentar de forma estructurada y accesible los principales fundamentos matemáticos de la Ciencia de Datos, vinculando la teoría con su aplicación práctica. A lo largo de las próximas entregas abordaremos los siguientes ejes:

    Álgebra lineal: el ABC de los datos

    Piensa en álgebra lineal como el sistema de archivos de la data science. Organiza datos en vectores (filas) y matrices (tablas), que son la base de todos los algoritmos.

    EdadSalarioExperiencia.
    2550.0002<– Vector 1
    3075.0005<– Vector 2
    3560.0008<– Vector 3

    Algoritmos como regresión lineal, redes neuronales y PCA trabajan con matrices para encontrar patrones.

    Aplicaciones Reales
    • Recomendaciones Netflix: Matrices de usuario-película
    • Reconocimiento facial: Vectores de píxeles convertidos en características
    • Google Maps: Cálculos matriciales para rutas óptimas

    Cálculo: Encontrando el Mejor Camino

    Imagina que quieres encontrar la mejor ruta desde tu casa al trabajo. El cálculo es como el GPS que evalúa cada posible camino y elige el más rápido. Derivadas, gradientes y métodos de descenso aplicados al aprendizaje automático.

    En machine learning, el gradiente es como una brújula que te dice hacia dónde moverte para mejorar tu modelo y qué tan rápido moverte.

    El Gradient Descent (descenso por gradiente) empieza con una suposición inicial, calcula el error y usa el gradiente para ajustar ligeramente los pesos hasta encontrar el mínimo error. Es como bajar una montaña con los ojos vendados, usando solo la pendiente del terreno para guiarte.

    Probabilidad y estadística: el arte de interpretar datos

    La estadística es como tener gafas especiales para ver patrones invisibles en tus datos. Te ayuda a responder: ¿Es real este patrón o solo casualidad?

    Estadísticas descriptivas

    Te describen tus datos —la media, la mediana, la varianza, la desviación estándar o los percentiles—, que permiten resumir y comprender la estructura esencial de la información, convirtiendo el caos de los datos brutos en conocimiento interpretable, proporcionando una base sólida para la exploración, la visualización y, finalmente, la inferencia estadística y el modelado predictivo.

    A través de ellas podemos detectar patrones generales, identificar valores atípicos, evaluar la consistencia de las mediciones y establecer hipótesis iniciales antes de aplicar modelos más complejos.

    Comprender las relaciones

    Uno de los pilares de la estadística aplicada en Ciencia de Datos es la correlación, una medida que permite cuantificar la fuerza y dirección de la relación entre dos variables. Analizar la correlación no solo revela patrones ocultos en los datos, sino que orienta la formulación de hipótesis y la construcción de modelos predictivos.

    Sin embargo, identificar una correlación no implica causalidad. Para determinar si una relación observada es estadísticamente significativa y no producto del azar, entran en juego las pruebas estadísticas.

    Validar la evidencia

    El valor p (p-value) mide hasta qué punto tu hallazgo podría deberse a la casualidad. Los intervalos de confianza, por su parte, definen el rango dentro del cual se espera que se encuentre el valor real del parámetro poblacional con una determinada probabilidad.

    Ambos conceptos permiten evaluar la significancia estadística, es decir, si el efecto detectado es lo suficientemente consistente como para considerarse real y no fruto de la variabilidad muestral.

    Historia real: En 2018, muchas empresas de tech descubrieron que sus “éxitos” en A/B testing eran solo ruido estadístico por no entender los p-values.

    Análisis de Datos y Modelado Matemático: De la Teoría a la Aplicación

    Finalmente, todos estos fundamentos convergen en la práctica del análisis de datos y el modelado matemático, donde las herramientas teóricas se integran para resolver problemas reales en contextos empresariales, científicos y sociales.

    El análisis de datos implica no solo explorar y describir información, sino también formular modelos que representen fenómenos observables, desde la predicción de la demanda en una cadena hotelera hasta la detección de anomalías en sistemas financieros o medioambientales.

    El modelado matemático convierte esas relaciones en expresiones cuantitativas, permitiendo simular escenarios, realizar proyecciones y evaluar decisiones estratégicas. Su poder radica en conectar el mundo abstracto de las ecuaciones con la realidad operativa de las organizaciones, donde cada decisión basada en datos puede traducirse en eficiencia, rentabilidad o innovación.

    No necesitas ser un genio matemático. Solo curiosidad y ganas de entender cómo funcionan las cosas detrás de Python y TensorFlow.

    ¿Cómo las matemáticas se conectan con Python?

    En la práctica moderna de la Ciencia de Datos, las matemáticas y Python forman una alianza inseparable. Mientras las matemáticas proporcionan el marco teórico para entender los algoritmos, Python ofrece las herramientas prácticas para implementarlos, visualizarlos y validarlos sobre datos reales.

    Cada concepto matemático puede trasladarse directamente al código:

    • El álgebra lineal se materializa a través de librerías como NumPy, que permite trabajar con vectores, matrices y operaciones matriciales de forma eficiente.
    • El cálculo y la optimización se aplican en entornos como TensorFlow o PyTorch, donde los gradientes y derivadas se calculan automáticamente durante el entrenamiento de modelos.
    • La probabilidad y estadística se ponen en práctica mediante Pandas, SciPy o Statsmodels, facilitando desde el análisis exploratorio hasta las pruebas de hipótesis.

    Python, por tanto, no reemplaza las matemáticas: las traduce en acción. Es el medio que permite pasar de la teoría a la experimentación, y de la experimentación al descubrimiento. Comprender las matemáticas detrás del código permite usar estas herramientas con criterio, interpretar correctamente los resultados y desarrollar soluciones más eficientes y explicables.

    En resumen, mientras las matemáticas aportan el “por qué”, Python ofrece el “cómo”. Juntas conforman el lenguaje operativo de la Ciencia de Datos moderna.