【问题标题】:Seaborn catplot (kind='count') change bar chart to pie chartSeaborn catplot (kind='count') 将条形图更改为饼图
【发布时间】:2020-09-21 23:28:54
【问题描述】:

我在 corona-tracking-apps 上的论文中使用了以下 df(在上面使用了 pd.melt):

    CTQ-tool    opinion
0   Information and awareness purposes  unacceptable
1   Information and awareness purposes  unacceptable
2   Information and awareness purposes  acceptable
3   Information and awareness purposes  acceptable
4   Information and awareness purposes  unacceptable
... ... ...
2827    Central/Local data storage  NaN
2828    Central/Local data storage  NaN
2829    Central/Local data storage  NaN
2830    Central/Local data storage  NaN
2831    Central/Local data storage  NaN
2832 rows × 2 columns

我正在使用 Seaborn 库制作以下 catplot:

代码:

g = sns.catplot("opinion", col="CTQ-tool", col_wrap=4, data=df_original_small, kind="count", height=6.5, aspect=.8)

但是,我不想将这些显示在条形图中,而是将它们显示为饼图。 Seaborn.catplot 不允许 kind='count-pie'。有谁知道解决方法吗?

在 TiTo 问题后编辑:

这基本上是我希望看到所有 8 个条形图发生的情况:

【问题讨论】:

标签: python pandas data-visualization seaborn pie-chart


【解决方案1】:

我最终使用 matplotlib 库从底层构建它:

plt.style.use('seaborn')

IAP = df_original_small['Information and awareness purposes'].value_counts().to_frame().T
QE = df_original_small['Quarantine Enforcement'].value_counts().to_frame().T
CTCR = df_original_small['Contact Tracing and Cross-Referencing'].value_counts().to_frame().T
VPID = df_original_small['Voluntary provision of infection data'].value_counts().to_frame().T
QMA = df_original_small['Quarantine Monitoring App'].value_counts().to_frame().T
QRCode = df_original_small['QR code provided registration tracking'].value_counts().to_frame().T

total = pd.concat([IAP, QE, CTCR, VPID, QMA, QRCode])

fig, ax = plt.subplots(nrows=3, ncols=2)

labels = 'acceptable', 'unacceptable'
colors = ['#008fd5', '#fc4f30']
explode = (0, 0.1)
explode2 = (0.2, 0)

plt.title('Pie chart per CTQ-tool')
plt.tight_layout()

ax[0,0].pie(total.iloc[[0]], startangle=90, colors=colors, wedgeprops={'edgecolor': 'black'}, autopct='%1.f%%', explode=explode, shadow=True)
ax[0,0].set_title('Information and awareness purposes', fontweight='bold')
ax[0,1].pie(total.iloc[[1]],  startangle=90, colors=colors, wedgeprops={'edgecolor': 'black'}, autopct='%1.f%%', explode=explode, shadow=True)
ax[0,1].set_title('Quarantine Enforcement', fontweight='bold')
ax[1,0].pie(total.iloc[[2]],  startangle=90, colors=colors, wedgeprops={'edgecolor': 'black'}, autopct='%1.f%%', explode=explode2, shadow=True)
ax[1,0].set_title('Contact Tracing and Cross-Referencing', fontweight='bold')
ax[1,1].pie(total.iloc[[3]], startangle=90, colors=colors, wedgeprops={'edgecolor': 'black'}, autopct='%1.f%%', explode=explode, shadow=True)
ax[1,1].set_title('Voluntary provision of infection data', fontweight='bold')
ax[2,0].pie(total.iloc[[4]], startangle=90, colors=colors, wedgeprops={'edgecolor': 'black'}, autopct='%1.f%%', explode=explode2, shadow=True)
ax[2,0].set_title('Quarantine Monitoring App', fontweight='bold')
ax[2,1].pie(total.iloc[[5]], startangle=90, colors=colors, wedgeprops={'edgecolor': 'black'}, autopct='%1.f%%', explode=explode, shadow=True)
ax[2,1].set_title('QR code provided registration tracking', fontweight='bold')


fig.suptitle('Public Opinion on CTQ-measures', fontsize=20, y=1.07, fontweight='bold', x=0.37)
fig.set_figheight(10)
fig.set_figwidth(7)
fig.legend(loc='best', labels=labels, fontsize='medium')
fig.tight_layout()

fig.savefig('Opinions_ctq')

plt.show()

【讨论】:

  • 我也在尝试这样做。所以你不能用 seaborn 做到这一点?
【解决方案2】:

如果你想要快速的东西,你也可以试试这个:

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

df = pd.DataFrame({'CTQ-tool':np.random.choice(['a','b','c','d'],50),
                  'opinion':np.random.choice(['acceptable','unacceptable'],50)})

fig, ax = plt.subplots(2,2)
ax = ax.flatten()
tab = pd.crosstab(df['CTQ-tool'],df['opinion'])
for i,cat in enumerate(tab.index):
    tab.loc[cat].plot.pie(ax=ax[i],startangle=90)
    ax[i].set_ylabel('')
    ax[i].set_title(cat, fontweight='bold')

【讨论】:

    【解决方案3】:

    问题是关于使用python 创建饼图,所以我认为您可以使用另一个可视化库,例如Plotly,除了作为可视化库之外,Plotly 是一个交互式可视化库,所以你所有的图表都是交互式的!

    快速查看pie chart documentation

    现在,针对您的问题,我创建了一个小型数据集并创建了两个饼图来说明代码的情况。

    • 首先,导入需要的库:
    import pandas as pd
    import plotly.graph_objects as go
    from plotly.subplots import make_subplots
    from kaleido.scopes.plotly import PlotlyScope # this will be used to export the chart as static image
    
    • 玩具数据集:
    df = pd.DataFrame(
        {
            "CTQ-tool": [
                "Information and awareness purposes",
                "Information and awareness purposes",
                "Information and awareness purposes",
                "Information and awareness purposes",
                "Information and awareness purposes",
                "Information and awareness purposes",
                "Quarantine Enforcement",
                "Quarantine Enforcement",
                "Quarantine Enforcement",
                "Quarantine Enforcement",
                "Quarantine Enforcement",
                "Quarantine Enforcement",
            ],
            "opinion": [
                "unacceptable",
                "unacceptable",
                "unacceptable",
                "unacceptable",
                "acceptable",
                "unacceptable",
                "acceptable",
                "unacceptable",
                "acceptable",
                "unacceptable",
                "unacceptable",
                "unacceptable",
            ],
        }
    )
    
    • 保存独特的不同工具
    tools = df["CTQ-tool"].unique()
    
    • 创建的汇总数据:

    以下代码将按工具类型和意见类型分组,然后为每个工具创建一个新列 counts 存储每个意见类型的计数。

    df_agg = df.groupby(by=["CTQ-tool", "opinion"]).size().reset_index(name="counts")
    

    新的数据框df_agg 将是:

    |      | CTQ-tool                           | opinion      | counts |
    | ---: | :--------------------------------- | :----------- | -----: |
    |    0 | Information and awareness purposes | acceptable   |      1 |
    |    1 | Information and awareness purposes | unacceptable |      5 |
    |    2 | Quarantine Enforcement             | acceptable   |      2 |
    |    3 | Quarantine Enforcement             | unacceptable |      4 |
    
    • 可视化数据(有趣的部分): 由于这个玩具数据只有两种不同的工具,因此我创建了一个 sub-plot,其中包含 onr 行和两列,但您可以将其扩展到任意数量的行/列。
    fig = make_subplots(rows=1, cols=2, specs=[[{"type": "domain"}, {"type": "domain"}]])
    

    然后分别添加每个图表(您可以使用 for 循环来完成):

    fig = make_subplots(rows=1, cols=2, specs=[[{"type": "domain"}, {"type": "domain"}]])
    
    # Information and awareness purposes tool
    fig.add_trace(
        go.Pie(
            values=df_agg[df_agg["CTQ-tool"] == tools[0]]["counts"],
            labels=df_agg[df_agg["CTQ-tool"] == tools[0]]["opinion"],
            pull=[0.2, 0.0],
            title=tools[0],
        ),
        1,
        1,
    )
    
    # Quarantine Enforcement tool
    fig.add_trace(
        go.Pie(
            values=df_agg[df_agg["CTQ-tool"] == tools[1]]["counts"],
            labels=df_agg[df_agg["CTQ-tool"] == tools[1]]["opinion"],
            pull=[0.2, 0.0],
            title=tools[1],
        ),
        1,
        2,
    )
    
    • 更新图表布局:
    fig.update_layout(title_text="Public Opinion on CTQ-measures")
    
    fig.show()
    
    • 最后,导出为静态图片:

    现在您已经准备好数据并将其可视化,是时候将其另存为图像了。 Plotly 创作者为此构建了一个工具:Kaleido

    你可以像下面这样简单地使用它:

    scope = PlotlyScope()
    fig_name = "Public-Opinion-on-CTQ-measures"
    with open(f"{fig_name}.png", "wb") as f:
        f.write(scope.transform(fig, "png"))
    

    这个数字是:

    【讨论】:

      猜你喜欢
      • 2019-08-30
      • 2021-06-18
      • 1970-01-01
      • 2021-09-25
      • 1970-01-01
      • 2011-01-23
      • 1970-01-01
      • 2019-04-01
      • 1970-01-01
      相关资源
      最近更新 更多