Columna blanca no deseada en matplotlib - cómo quitar?

aquí está el código de pitón (portando del excelente Repensamiento Estadístico de Richard McElreath) que resulta en un 'column' transparente blanco no deseado en mi trama resultante:

import numpy as np
import pandas as pd
import scipy.stats

import matplotlib.pyplot as plt

# import data
url = "https://raw.githubusercontent.com/pymc-devs/resources/master/Rethinking_2/Data/Howell1.csv"


df = pd.read_csv(url, delimiter = ';')
df2 = df[df.age >= 18]

# sample priors (prior predictive check)

n = 100
a = scipy.stats.norm.rvs(178, 20, n)
b1 = scipy.stats.norm.rvs(0, 10, n)
b2 = np.exp(scipy.stats.norm.rvs(0, 1, n))

xbar = df2.weight.mean()


# compare 2 priors

fig,ax = plt.subplots(1,2,sharey=True)

for i in range(100):
    ax[0].plot(df2.weight, a[i] + b1[i]*(df2.weight - xbar),color = 'grey',lw=.5,alpha=.2)
    ax[0].set_xlabel('weight')
    ax[0].set_ylabel('height')
    ax[0].set_title('normal prior of β')
    ax[1].plot(df2.weight, a[i] + b2[i]*(df2.weight - xbar),color = 'grey',lw=.5,alpha=.2)
    ax[1].set_xlabel('weight')
    ax[1].set_title('log-normal prior of β')

plt.axis([30,60,-100,400])
plt.show()

matplotlib output

Esto ocurre en mi cuaderno Jupyter, en Google CoLab y en el pdf (plt.savefig)

Mis versiones de notebook: numposo 1.19.4 pandas 1.1.5 disciplina 1.5.4 matplotlib 3.3.3

¡Gracias!

Pregunta hecha hace 3 años, 4 meses, 28 días - Por nasean


5 Respuestas:

  • Creo que te refieres a la región donde las líneas se dibujan más delgadas y no las fronteras.

    Descubrí que tiene que ver con el aliado y no con los datos mismos.

    Jugar alrededor con el antialiased parámetro:

    ax[0].plot(..., antialiased=False)
    

    Parece que esto:

    enter image description here

    Seguramente hace que la trama parezca fea pero puede aumentar el tamaño de la figura o el parámetro dpi.

    fig.set_dpi(300.0)
    ...
    plt.show();
    

    Entonces tienes esto:

    enter image description here

    Respondida el Dec 17, 2020 a las 15:17 - por cybermage

    Votos positivos: 0 | Votos negativos: 0

  • Este es un artefacto de datos que interactúa con el anti-aliasing de una manera interesante. En la imagen final tenemos que elegir un color para cada pixel. Sin anti-aliasing cuando tenemos que dibujar una línea tenemos que decidir es este pixel "en" la línea (y por lo tanto la coloramos) o "out" (en cuyo caso no la coloramos) que puede conducir a líneas de aspecto escalera (en particular con líneas que son cerca a plana). Con anti-aliasing coloramos el píxel basado en cuánto del píxel está "en" la línea vs no. Esa mirada nos engaña (de buena manera) y vemos una línea recta más convincente. Sin anti-aliasing o alfa dibujando la misma línea varias veces no cambia la apariencia (cualquier pixel dado está todavía dentro o fuera), pero con anti-aliasing o alfa, cada vez que dibuja la línea cualquiera de los píxeles "partiales" se vuelve más oscuro.

    En los datos originales los valores df2.weight todos caen en la misma línea, pero no están ordenados de modo que lo dibujamos va de vuelta a adelante sobre el mismo camino (ver el rastro en el panel del centro izquierdo). Dependiendo de exactamente dónde están los puntos de inflexión y cuántas veces cualquier segmento dado se atraviesa la línea se verá más oscura en algunos lugares que otros. Hay algo en la estructura exacta de los datos que está causando ese "banda".

    Si aumentas el DPI, los píxeles se vuelven más pequeños para que el efecto se pronuncie menos (similar a ampliar) y si giras de anti-aliasing el efecto se hará menos pronunciado. Sospecho (pero no lo han probado) si usted elimina los datos que usted será capaz de mover la banda alrededor!

    Clasificación de los pesos (que desde este contexto no creo que su orden sea significativo?) hace las parcelas en los dos paneles inferiores que se ven más agradables.

    Así que en resumen, esa banda es "real" en el sentido de que representa algo en los datos en lugar de ser un error en el proceso de renderizado, pero está resaltando la estructura en los datos que no creo que sea significativo.

    import numpy as np
    import pandas as pd
    import scipy.stats
    
    import matplotlib.pyplot as plt
    
    # import data
    url = "https://raw.githubusercontent.com/pymc-devs/resources/master/Rethinking_2/Data/Howell1.csv"
    
    # this is a mpl 3.3 feature
    fig, ad = plt.subplot_mosaic(
        [
            ["normal", "log-normal"],
            ["trace", "hist"],
            ["sorted normal", "sorted log-normal"],
        ],
        constrained_layout=True,
    )
    
    df = pd.read_csv(url, delimiter=";")
    df2 = df[df.age >= 18]
    # sample priors (prior predictive check)
    
    n = 100
    a = scipy.stats.norm.rvs(178, 20, n)
    b1 = scipy.stats.norm.rvs(0, 10, n)
    b2 = np.exp(scipy.stats.norm.rvs(0, 1, n))
    
    
    def inner(weights, a, b1, b2, ax_dict):
        xbar = np.mean(weights)
        for i in range(100):
            ax_dict["normal"].plot(
                weights, a[i] + b1[i] * (weights - xbar), color="grey", lw=0.5, alpha=0.2
            )
            ax_dict["normal"].set_xlabel("weight")
            ax_dict["normal"].set_ylabel("height")
            ax_dict["normal"].set_title("normal prior of β")
            ax_dict["log-normal"].plot(
                weights, a[i] + b2[i] * (weights - xbar), color="grey", lw=0.5, alpha=0.2
            )
            ax_dict["log-normal"].set_xlabel("weight")
            ax_dict["log-normal"].set_title("log-normal prior of β")
    
    
    inner(df2.weight, a, b1, b2, ad)
    inner(
        np.array(sorted(df2.weight)),
        a,
        b1,
        b2,
        {"normal": ad["sorted normal"], "log-normal": ad["sorted log-normal"]},
    )
    
    ad["hist"].hist(df2.weight, bins=100, color="0.5")
    ad["hist"].set_xlabel("weight")
    ad["hist"].set_ylabel("#")
    ad["trace"].plot(df2.weight, "-o", color="0.5", alpha=0.5)
    ad["trace"].set_ylabel("weight")
    ad["trace"].set_xlabel("index")
    plt.show()
    

    enter image description here

    Respondida el Dec 17, 2020 a las 15:22 - por hackharbinger

    Votos positivos: 0 | Votos negativos: 0

  • Fijo los valores manualmente, pero si fijas los ejes para cada gráfico, los márgenes desaparecerán.

    ax[0].axis([33,63,-100,400])
    ax[1].axis([33,60,-100,400])
    

    enter image description here

    Si quieres que el espaciado entre los gráficos sea más estrecho, puedes hacerlo de la siguiente manera.

    fig.subplots_adjust(wspace=0.05)
    

    enter image description here

    Respondida el Dec 17, 2020 a las 15:29 - por syntaxsniper

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás experimentando con la presencia de esas columnas blancas en tu gráfica es debido a cómo estás realizando el bucle en tu código. El problema radica en que estás configurando las etiquetas de los ejes y títulos por cada iteración dentro del bucle, lo cual provoca que se superpongan y resulten en la aparición de las columnas blancas no deseadas en tu gráfico.

    Para solucionarlo, debes mover las líneas donde se configuran las etiquetas de los ejes y títulos fuera del bucle for i in range(100):. De esta forma, estas configuraciones se realizarán una sola vez y no se repetirán en cada iteración del bucle, evitando así el problema de las columnas blancas.

    Aquí te dejo el código modificado:

    ```python import numpy as np import pandas as pd import scipy.stats

    import matplotlib.pyplot as plt

    import data

    url = "https://raw.githubusercontent.com/pymc-devs/resources/master/Rethinking_2/Data/Howell1.csv"

    df = pd.read_csv(url, delimiter=';') df2 =

    Respondida el Dec 18, 2020 a las 15:16 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • La columna blanca no deseada en tu trama de Matplotlib es causada por el uso de ax.plot() para dibujar las líneas de regresión. ax.plot() dibuja una línea entre cada par de puntos en tus datos, y en este caso, estás proporcionando solo un conjunto de valores y (los pesos) y sin valores x. Esto hace que ax.plot() conecte cada peso con el siguiente, creando la línea vertical.

    Para solucionar este problema, debes proporcionar valores x para tus líneas de regresión. En este caso, puedes usar los pesos como valores x:

    python
    for i in range(100):
        ax[0].plot(df2.weight, a[i] + b1[i](df2.weight - xbar),color = 'grey',lw=.5,alpha=.2)
        ax[0].set_xlabel('weight')
        ax[0].set_ylabel('height')
        ax[0].set_title('normal prior of β')
        ax[1].plot(df2.weight, a[i] + b2[i](df2.weight - xbar),color = 'grey',lw=.5,alpha=.2)
        ax[1].set_xlabel('weight')
        ax[1].set_title('log-normal prior of β')
    

    También puedes utilizar la función ax.scatter() para dibujar las líneas de regresión. ax.scatter() dibuja un punto para cada par de valores x e y, y no conectará los puntos.

    python
    for i in range(100):
        ax[0].scatter(df2.weight, a[i] + b1[i](df2.weight - xbar),color = 'grey',lw=.5,alpha=.2)
        ax[0].set_xlabel('weight')
        ax[0].set_ylabel('height')
        ax[0].set_title('normal prior of β')
        ax[1].scatter(df2.weight, a[i] + b2[i](df2.weight - xbar),color = 'grey',lw=.5,alpha=.2)
        ax[1].set_xlabel('weight')
        ax[1].set_title('log-normal prior of β')
    

    Ambos métodos deberían eliminar la columna blanca no deseada de tu trama.

    Respondida el Dec 18, 2020 a las 15:17 - por Gemini

    Votos positivos: 0 | Votos negativos: 0