Seaborn Factorplot генерирует дополнительные пустые участки под фактическим участком - PullRequest
0 голосов
/ 02 марта 2019

All,

Я пытаюсь построить два факторных графика с использованием функции subplots и библиотеки Seaborn.Мне удалось построить два участка отдельно, используя приведенный ниже код.Тем не менее, seaborn создает дополнительный график ниже фактических графиков (см. Изображение ниже).Есть ли способ избежать seaborn для создания дополнительного пустого графика?Я пытался plt.close избавиться от сюжетов, но, к сожалению, он просто закрыл 1 сюжет. Кроме того, я пытаюсь убрать легенду из сюжета и отобразить легенду рядом с сюжетами.Есть ли простой способ сделать это.Я попробовал legend_out доступный в seaborn пакете, но это не сработало.

Мой код:

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.show()

Вывод вышеуказанного кода:

enter image description here

Примечание: я новичок в Python, пожалуйста, предоставьте объяснение с вашим кодом.

Пропускная способность кадра данных

#n dataframe
{'borough': {0: 'Bronx', 1: 'Brooklyn', 2: 'EWR', 3: 'Manhattan', 4: 'Queens', 5: 'Staten Island', 6: 'Unknown'}, '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
{'borough': {2: 'EWR', 5: 'Staten Island', 6: 'Unknown'}, 'pickups': {2: 0.02417683628827999, 5: 1.6018880957863229, 6: 2.0571804140650674}}

Ответы [ 2 ]

0 голосов
/ 10 марта 2019

Обратите внимание, что factorplot называется 'catplot' в более поздних версиях Seaborn.

catplot или factorplot - цифрыфункции уровня.Это означает, что они должны работать на уровне фигуры, а не на уровне осей.

Что происходит в вашем коде:

f,axes=plt.subplots(1,2,figsize=(8,4))
  • Это создает «Рисунок 1».
sns.factorplot(x="borough", y="pickups", hue="borough", kind='bar', data=n, size=4, aspect=2,ax=axes[0])
  • Это создает «Рисунок 2», но вместо того, чтобы рисовать Figure 2, вы говорите, что Seaborn должен рисовать axes[0] из Figure 1так что Figure 2 остается пустым.
sns.factorplot(x="borough", y="pickups", hue="borough", kind='bar', data=low_pickups, size=4, aspect=2,ax=axes[1])
  • Теперь это снова создает фигуру: Figure 3 и здесь вы также говорите, что Seaborn должен рисовать на осях от Figure 1, axes[1] то есть.
plt.close(2)
  • Здесь вы закрываете пустой Figure 2, созданный seaborn.

Итак, теперь у вас осталось Figure 1 с двумя осями, которые вы как бы «впрыскивали» в вызовы factorplot, и с еще пустой цифрой Figure 3, созданной во втором вызовеfactorplot но никогда не пишите ничего: (.

plt.show()
  • И теперь вы видите Figure 1 с 2 осями и Figure 3 с пустым графиком.

    Это при запуске в терминале, в ноутбуке вы можете просто увидеть две цифры одна под другой, выглядящие как фигура с 3 осями.


Как это исправить:

У вас есть 2 варианта:

1. Быстрый:

Просто закройте Figure 3 до 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()

По сути, вы закорачиваете часть factorplot, которая создает фигуру и оси для рисования, предоставляя ваши "пользовательские" оси из Figure 1. Вероятно, не то, для чего factorplot было разработано, ноэй, если это работает, это работает ... и это делает.

2. Правильный:

Пусть функция уровня фигуры делает свою работу и создает свою собственнуюцифры.Что вам нужно сделать, это указать, какие переменные вы хотите использовать в качестве столбцов.

Так как кажется, что у вас есть 2 фрейма данных, n и low_pickups, вы должны сначала создать из них один фрейм данных с помощьюв столбце написано cat, то есть n или 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)

Теперь вы можете создать свою фигуру с помощью одного вызова sns.catplot (или sns.factorplot в вашем случае), используяпеременная cat в виде столбца:

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()

Примечание : sharey=False требуется, так как по умолчанию оно будет истинным, и вы по существу не увидите значений на 2-й панелитак как они значительно меньше, чем на первой панели.

Версия 2. затем дает: enter image description here

Вывозможно, все еще понадобится немного стиля, но я оставлю это вам;).

Надеюсь, это помогло!

0 голосов
/ 10 марта 2019

Я думаю, это потому, что сам FactorPlot использует подзаговор.

РЕДАКТИРОВАТЬ 2019-march-10 18:43 GMT: И это подтверждается исходным кодом seaborn для categoryorical.py : для catplot (и factorplot) используется подспот matplotlib.Ответ @ Jojo прекрасно объясняет, что происходит

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

И axisgrid.py исходный код, который содержит определение 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)

Так что да,вы создавали множество подзаговоров, не зная об этом, и перепутали их с параметром ax=....@ Jojo прав.


Вот еще несколько вариантов:

Опция 1 enter image description here

Опция 2 enter image description here

Остерегайтесь того, что факторплот в устаревших версиях 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()

Консольные выходы:

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

Или попробуйте это:

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

Мне пришлось использовать шкалу y log, поскольку значения данных довольно сильно разбросаны.Вы можете рассмотреть возможность создания категорий (см. Раздел «Панды»)

РЕДАКТИРОВАТЬ 2019-march-10 18:43 GMT: как сказал @Jojo в своем ответе, последний вариант действительно был:

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

Не успел закончить исследование, поэтому вся заслуга ему!

...