Seaborn Factorplot在实际绘图下方生成额外的空图

问题描述 投票:6回答:2

所有,

我试图使用子图函数和Seaborn库绘制两个Factorplots。我能够使用下面的代码分别绘制两个图。然而,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}}
python matplotlib plot visualization seaborn
2个回答
8
投票

请注意,factorplot在更新版本的seaborn中被称为'catplot'

catplotfactorplot是数字级函数。这意味着它们应该在图形的水平上工作,而不是在轴的水平上工作。

您的代码中发生了什么:

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 1axes[1]的轴上绘制。
plt.close(2)
  • 在这里你关闭由seaborn创建的空Figure 2

所以现在你留下Figure 1与两个轴你有点'注入'factorplot调用和仍然空Figure 3数字是由factorplot的第二次调用创建但从来没有任何内容:(。

plt.show()
  • 现在你看到Figure 1有2个轴和Figure 3有一个空的情节。 这是在终端中运行时,在笔记本中你可能只看到一个在另一个下面的两个数字,看起来是一个有3个轴的数字。

如何解决这个问题:

你有2个选择:

1. The quick one:

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. The correct one:

让图形级别功能完成其工作并创建自己的数字。您需要做的是指定要作为列的变量。

由于您似乎有2个数据框,nlow_pickups,您应首先使用列catn列中的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=Falseis它是真的,你基本上看不到第二个面板中的值,因为它们比第一个面板中的值要小得多。

版本2.然后给出:enter image description here

您可能仍需要一些样式,但我会留给您;)。

希望这有帮助!


2
投票

我猜这是因为FactorPlot本身使用子图。

编辑2019-march-10 18:43 GMT:从seaborn source code for categorical.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

和包含FacetGrid定义的axisgrid.py源代码:

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)

所以是的,你在不知道它的情况下创建了很多子图,并用qazxsw poi参数搞砸了它们。 @Jojo是对的。


以下是一些其他选项:

选项1 ax=...

选项2 enter image description here

请注意,factorplot在较高的seaborn版本中已被弃用。

enter image description here

控制台输出:

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

我不得不使用y log scale,因为数据值在很大的范围内非常分散。你可以考虑做类别(参见大熊猫的剪辑)

编辑2019-march-10 18:43 GMT:正如@Jojo在答案中所述,最后一个选项确实是:

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

没有时间完成研究,所以所有的功劳归于他!

© www.soinside.com 2019 - 2024. All rights reserved.