python 了解FacetGrid/Barplot不一致性

xqkwcwgp  于 2023-06-20  发布在  Python
关注(0)|答案(2)|浏览(113)

我正在做一些EDA,我观察到Seaborn的以下行为。

海运版本0.12.2
Matplotlib版本3.7.1
输入数据

import pandas as pd
import seaborn as sns

data = {'Class': [0, 1, 1, 1, 1, 0, 1, 0, 1],
        'count': [509, 61, 18, 29, 8, 148, 54, 361, 46],
        'greek_char': ['Alpha', 'Alpha', 'Alpha', 'Alpha', 'Beta', 'Beta', 'Beta', 'Beta', 'Beta'],
        'value': ['A', 'B', 'D', 'G', 'A', 'B', 'B', 'C', 'C']}

df = pd.DataFrame(data)

编码

fig = sns.FacetGrid(data=df, col="greek_char", hue="Class")

\_ = fig.map_dataframe(sns.barplot, x="value", y="count", dodge=True)

我得到了以下图表:

以下是一些不一致之处:

  • 请注意,Alpha在数据集中没有C,但它出现在图表中。
  • Alpha A只有Class 0,但是,我在图中看到了两个类。
  • 图中缺少G类和D类。

我将感谢任何帮助,以确定此行为是否是一个错误,预期的行为,或者如果我错过了什么。

owfi6suc

owfi6suc1#

警告:在大多数情况下,最好使用图形级函数(例如relplot()catplot()),而不是直接使用FacetGrid

  • 在这种情况下没有理由使用FacetGrid
  • 使用catplot正确绘图解决了数据未在正确的'value'中绘图的问题。
  • 此外,'Beta''value': B & C具有重叠的'Class'数据,这意味着条形图是分层的,而不是堆叠的。分层条形图是一种非标准的数据表示方式,很可能会被误解。
  • seaborn.barplot不做堆叠条。
  • 有几个选项可以正确绘制数据:

1.应避开这些条。- 这是最好的选择

  • sns.displotkind='hist'可以堆叠条。
  • 这是一种使用histplot的方法,可能会有不可预见的行为,例如为'Beta'包含额外的x轴位置。
  • 条形图可以在x轴上绘制一个唯一的值,然后用正确的'value'重新标记。
  • df.reset_index(names=['x-axis'], inplace=True)将生成一组唯一的值,以在x轴上绘制。

1.设置'value'在x轴上的顺序可以通过以下方式完成:

  1. df.sort_values(['greek_char', 'value'], inplace=True)pd.DataFrame.sort_values
    1.或者,也可以使用pd.Categorical,但这会强制所有'value'类别都位于两个x轴上。
    1.* * 在python 3.11.3pandas 2.0.2matplotlib 3.7.1seaborn 0.12.2中测试**

1. dodge=True

g = sns.catplot(kind='bar', data=df, x='value', y='count', hue='Class', col='greek_char', sharey=False)

2. histplot

g = sns.displot(kind='hist', data=df, x='value', weights='count', hue='Class', col='greek_char', multiple='stack', shrink=0.9, facet_kws={'sharey': False, 'sharex': False})

3. dodge=False唯一标签

g = sns.catplot(kind='bar', data=df, x='x-axis', y='count', hue='Class', col='greek_char', sharey=False, sharex=False, dodge=False)

# iterate through each facet (axes)
for ax in g.axes.flat:
    # get the title to be used to select the correct data
    gc = ax.get_title().split(' = ')[1]
    # extract the values to be used for xticklabels
    xtick_labels = df.loc[df.greek_char.eq(gc), 'value'].tolist()
    # set the labels
    ax.set_xticks(ax.get_xticks(), xtick_labels)

  • 一般来说,pandas.DataFrame.plotkind='bar'以及stacked=True是绘制堆叠条形图的最佳选择,因为API专门为实现它们而设计。
# create the figure and subplot axes
fig, axes = plt.subplots(1, 2, figsize=(9, 4), tight_layout=True)

# iterate through each axes, and the group / data of the groupby object
for ax, (g, data) in zip(axes, df.groupby('greek_char')):
    
    # pivot the data into a wide-form
    data = data.pivot(index='value', columns='Class', values='count')
    
    # plot the stacked bars
    data.plot(kind='bar', stacked=True, rot=0, ylabel='count', title=g, ax=ax)
    
    # cosmetic change
    ax.spines[['top', 'right']].set_visible(False)
    
# adjust the legends so there is only one
axes[0].get_legend().remove()
axes[1].legend(title='Class', bbox_to_anchor=(1, 0.5), loc='center left', frameon=False)

df

df.sort_values(['greek_char', 'value'], inplace=True)
df.reset_index(names=['x-axis'], inplace=True)

   x-axis  Class  count greek_char value
0       0      0    509      Alpha     A
1       1      1     61      Alpha     B
2       2      1     18      Alpha     D
3       3      1     29      Alpha     G
4       4      1      8       Beta     A
5       5      0    148       Beta     B
6       6      1     54       Beta     B
7       7      0    361       Beta     C
8       8      1     46       Beta     C
1qczuiv0

1qczuiv02#

如果您尝试使用fig.map而不是fig.map_dataframe运行代码,您将得到警告UserWarning: Using the barplot function without specifying 'order' is likely to produce an incorrect plot.一旦我添加了order参数,我就得到了正确的图。

import pandas as pd
import seaborn as sns

data = {"Class":[0, 1, 1, 1, 1, 0, 1, 0, 1],
        "count":[509, 61, 18, 29, 8, 148, 54, 361, 46],
        "greek_char":["Alpha"]*4 + ["Beta"]*5,
        "value":["A", "B", "D", "G", "A", "B", "B", "C", "C"]}

df = pd.DataFrame(data)

fig = sns.FacetGrid(data=df, col="greek_char", hue="Class")
fig = fig.map_dataframe(sns.barplot, 
                        x="value", 
                        y="count", 
                        order=sorted(df["value"].unique()))
fig.add_legend()

相关问题