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, 29 días - Por techtrailblazer8d2c


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:16 - por algoarchitect

    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 pixelpioneerx

    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:30 - por debugdynamo

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás experimentando con la columna blanca no deseada en tu trama de matplotlib se debe a que estás modificando las propiedades de los ejes y los títulos dentro del bucle for, lo cual no es necesario ya que estas propiedades deben establecerse una sola vez fuera del bucle. Es por eso que estás viendo que las propiedades se aplican repetidamente en cada iteración del bucle, generando esa apariencia no deseada.

    Para solucionar este problema, debes mover la configuración de las propiedades de los ejes y los títulos fuera del bucle for. Aquí te dejo el código corregido:

    ``` 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 = df[df.age >= 18]

    sample priors (prior predictive check)

    n = 100 a = scipy.stats.norm.rvs(178, 20, n) b1

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

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás experimentando con la columna blanca adicional en tu trama de Matplotlib probablemente se debe a la función sharey=True que has utilizado al crear tus subplots. Esta función fuerza a que ambos subplots compartan el mismo eje y, en tu caso, está creando la columna blanca adicional para acomodar el rango de valores del subplot derecho, que es más amplio que el del subplot izquierdo.

    Para solucionar este problema, puedes eliminar la función sharey=True de tu código. De esta manera, cada subplot tendrá su propio eje y y no se creará la columna blanca adicional.

    Aquí tienes 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 = 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) 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()

    Espero que esto resuelva el problema de la columna blanca en tu trama.

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

    Votos positivos: 0 | Votos negativos: 0