Saltar al contenido

Seaborn Factorplot genera parcelas vacías adicionales debajo de la parcela real

Solución:

Tenga en cuenta que factorplot se llama ‘catplot’ en versiones más recientes de seaborn.

catplot o factorplot son funciones a nivel de figura. Esto significa que se supone que funcionan al nivel de una figura y no al nivel de los ejes.

Qué está sucediendo en tu código:

f,axes=plt.subplots(1,2,figsize=(8,4))
  • Esto crea la ‘Figura 1’.
sns.factorplot(x="borough", y="pickups", hue="borough", kind='bar', data=n, size=4, aspect=2,ax=axes[0])
  • Esto crea ‘Figura 2’ pero en lugar de dibujar en Figure 2 le dices a seaborn que dibuje en axes[0] de Figure 1, asi que Figure 2 permanece vacío.
sns.factorplot(x="borough", y="pickups", hue="borough", kind='bar', data=low_pickups, size=4, aspect=2,ax=axes[1])
  • Ahora esto crea una vez más una figura: Figure 3 y aquí, también, le dices a seaborn que dibuje en un hacha de Figure 1, axes[1] es decir.
plt.close(2)
  • Aqui cierras el vacio Figure 2 creado por seaborn.

Así que ahora te quedas con Figure 1 con los dos ejes que un poco ‘inyectaste’ en el factorplot llamadas y con el aun vacio Figure 3 figura que fue creada por la 2da convocatoria de factorplot pero nunca sah ningún contenido :(.

plt.show()
  • Y ahora ves Figure 1 con 2 ejes y el Figure 3 con una parcela vacía.

    Esto es cuando se ejecuta en la terminal, en una computadora portátil, es posible que vea las dos figuras una debajo de la otra que parecen ser una figura con 3 ejes.


Cómo arreglar esto:

Tienes 2 opciones:

1. El rápido:

Simplemente cerrar Figure 3 antes de plt.show():

f,axes=plt.subplots(1,2,figsize=(8,4))

sns.factorplot(x="borough", y="pickups", hue="borough", kind='bar', data=n, size=4, aspect=2,ax=axes[0])

sns.factorplot(x="borough", y="pickups", hue="borough", kind='bar', data=low_pickups, size=4, aspect=2,ax=axes[1])
plt.close(2)
plt.close(3)
plt.show()

Básicamente estás cortocircuitando la parte de factorplot que crea una figura y ejes sobre los que dibujar proporcionando sus ejes “personalizados” de Figure 1. Probablemente no lo que factorplot fue diseñado para, pero bueno, si funciona, funciona … y funciona.

2. El correcto:

Deje que la función de nivel de figura haga su trabajo y cree sus propias figuras. Lo que debe hacer es especificar qué variables desea como columnas.

Dado que parece que tiene 2 marcos de datos, n y low_pickups, primero debe crear un único marco de datos a partir de ellos con la columna que dice cat eso es o n o low_pickups:

# assuming n and low_pickups are a pandas.DataFrame:
# first add the 'cat' column for both
n['cat'] = 'n'
low_pickups['cat'] = 'low_pickups'
# now create a new dataframe that is a combination of both
comb_df = n.append(low_pickups)

Ahora puedes crear tu figura con una sola llamada a sns.catplot (o sns.factorplot en tu caso) usando la variable cat como columna:

sns.catplot(x="borough", y="pickups", col="cat", hue="borough", kind='bar', sharey=False, data=comb_df, size=4, aspect=1)
plt.legend()
plt.show()

Nota: Los sharey=Falsees obligatorio, ya que de forma predeterminada sería cierto y, en esencia, no vería los valores en el segundo panel, ya que son considerablemente más pequeños que los del primer panel.

La versión 2. luego da:
ingrese la descripción de la imagen aquí

Es posible que aún necesite un poco de estilo, pero se lo dejo a usted;).

¡Espero que esto haya ayudado!

Supongo que esto se debe a que FactorPlot en sí usa una subtrama.

EDITAR 2019-march-10 18:43 GMT: Y está confirmado a partir del código fuente de seaborn para categorical.py: la trama de gato (y la trama de factor) usan la trama secundaria de matplotlib. La respuesta de @Jojo explica perfectamente lo que está sucediendo.

def catplot(x=None, y=None, hue=None, data=None, row=None, col=None,
            col_wrap=None, estimator=np.mean, ci=95, n_boot=1000,
            units=None, order=None, hue_order=None, row_order=None,
            col_order=None, kind="strip", height=5, aspect=1,
            orient=None, color=None, palette=None,
            legend=True, legend_out=True, sharex=True, sharey=True,
margin_titles=False, facet_kws=None, **kwargs):
    ... # bunch of code
    g = FacetGrid(**facet_kws) # uses subplots

Y el código fuente de axisgrid.py que contiene la definición de FacetGrid:

class FacetGrid(Grid):
    def __init(...):
        ... # bunch of code
        # Build the subplot keyword dictionary
        subplot_kws = {} if subplot_kws is None else subplot_kws.copy()
        gridspec_kws = {} if gridspec_kws is None else gridspec_kws.copy()
        # bunch of code
        fig, axes = plt.subplots(nrow, ncol, **kwargs)

Así que sí, estabas creando muchas subtramas sin saberlo y las arruinaste con el ax=... parámetro. @ Jojo tiene razón.


Aquí hay algunas otras opciones:

Opción 1
ingrese la descripción de la imagen aquí

opcion 2
ingrese la descripción de la imagen aquí

Tenga en cuenta que factorplot está obsoleto en versiones superiores de Seaborn.

import pandas as pd
import seaborn as sns
import matplotlib
import matplotlib.pyplot as plt

print(pd.__version__)
print(sns.__version__)
print(matplotlib.__version__)

# n dataframe
n = pd.DataFrame(
    {'borough': {0: 'Bronx', 1: 'Brooklyn', 2: 'EWR', 3: 'Manhattan', 4: 'Queens', 5: 'Staten Island', 6: 'Unknown'},
     'kind': {0: 'n', 1: 'n', 2: 'n', 3: 'n', 4: 'n', 5: 'n', 6: 'n'},
     'pickups': {0: 50.66705042597283, 1: 534.4312687082662, 2: 0.02417683628827999, 3: 2387.253281142068,
                 4: 309.35482385447847, 5: 1.6018880957863229, 6: 2.0571804140650674}})
# low_pickups dataframe
low_pickups = pd.DataFrame({'borough': {2: 'EWR', 5: 'Staten Island', 6: 'Unknown'},
                            'kind': {0: 'low_pickups', 1: 'low_pickups', 2: 'low_pickups', 3: 'low_pickups',
                                     4: 'low_pickups', 5: 'low_pickups', 6: 'low_pickups'},
                            'pickups': {2: 0.02417683628827999, 5: 1.6018880957863229, 6: 2.0571804140650674}})

new_df = n.append(low_pickups).dropna()

print(n)
print('--------------')
print(low_pickups)
print('--------------')
print(new_df)

g = sns.FacetGrid(data=new_df, col="kind", hue="kind", sharey=False)
g.map(sns.barplot, "borough", "pickups", order=sorted(new_df['borough'].unique()))
plt.show()

Salidas de consola:

0.24.1
0.9.0
3.0.2
         borough kind      pickups
0          Bronx    n    50.667050
1       Brooklyn    n   534.431269
2            EWR    n     0.024177
3      Manhattan    n  2387.253281
4         Queens    n   309.354824
5  Staten Island    n     1.601888
6        Unknown    n     2.057180
--------------
         borough         kind   pickups
0            NaN  low_pickups       NaN
1            NaN  low_pickups       NaN
2            EWR  low_pickups  0.024177
3            NaN  low_pickups       NaN
4            NaN  low_pickups       NaN
5  Staten Island  low_pickups  1.601888
6        Unknown  low_pickups  2.057180
--------------
         borough         kind      pickups
0          Bronx            n    50.667050
1       Brooklyn            n   534.431269
2            EWR            n     0.024177
3      Manhattan            n  2387.253281
4         Queens            n   309.354824
5  Staten Island            n     1.601888
6        Unknown            n     2.057180
2            EWR  low_pickups     0.024177
5  Staten Island  low_pickups     1.601888
6        Unknown  low_pickups     2.057180

O prueba esto:

g = sns.barplot(data=new_df, x="kind", y="pickups", hue="borough")#, order=sorted(new_df['borough'].unique()))
g.set_yscale('log')

Tuve que usar la escala logarítmica y ya que los valores de los datos están bastante dispersos en un rango enorme. Puede considerar hacer categorías (vea el corte de pandas)

EDITAR 2019-March-10 18:43 GMT: como dijo @Jojo en su respuesta, la última opción fue:

sns.catplot(data=new_df, x="borough", y="pickups", col="kind", hue="borough", sharey=False, kind='bar')

No tuve tiempo de terminar el estudio, ¡así que todo el mérito es para él!

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *