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 enaxes[0]
deFigure 1
, asi queFigure 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 deFigure 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 elFigure 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=False
es 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:
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
opcion 2
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!