颜色不一致地应用于子批次中的类别

2024-09-20 22:52:23 发布

您现在位置:Python中文网/ 问答频道 /正文

有下面的代码,我不明白为什么不能正确显示信息(检查C列和F列)bot显示为相同的值,但不同

我需要的是绘制df中的一些列,并在所有子图之间共享图例 (所有列都有相同的值[“SI”,“NO”] (这只是一个示例代码)

colnames=['a','b','c','d','e','f','g']
values=[
    ['SI','SI','NO','SI','SI','SI','NO'],
    ['SI','NO','NO','SI','NO','SI','NO'],
    ['SI','SI','NO','SI','SI','SI','NO'],
    ['SI','NO','NO','NO','NO','SI','SI'],
    ['SI','NO','NO','NO','NO','SI','NO']]

df=pd.DataFrame(values, columns=colnames)

def pieplotstest(df):
    fig,ax =plt.subplots(2,3,facecolor=(1, 1, 1),figsize=(7.2,4.3))
    plt.style.use('fivethirtyeight')

    colors=["#172a3d","#e33e31"]
    textprops=dict(color="w",weight='bold',size=5)
    labels=['NO','SI']

    ax[0,0].pie(df['b'].value_counts(),
            colors=colors,
            autopct = '%1.1f%%',
            textprops=textprops,
            wedgeprops=dict(width=0.5),
            pctdistance=0.7
        )
    ax[0,1].pie(df['c'].value_counts(),
            colors=colors,
            autopct = '%1.1f%%',
            textprops=textprops,
            wedgeprops=dict(width=0.5),
            pctdistance=0.75

        )
    ax[0,2].pie(df['d'].value_counts(),
            colors=colors,
            autopct = '%1.1f%%',
            textprops=textprops,
            wedgeprops=dict(width=0.5),
            pctdistance=0.75
        )
    ax[1,0].pie(df['e'].value_counts(),
            colors=colors,
            autopct = '%1.1f%%',
            textprops=textprops,
            wedgeprops=dict(width=0.5),
            pctdistance=0.75
        )
    ax[1,1].pie(df['f'].value_counts(),
            colors=colors,
            autopct = '%1.1f%%',
            textprops=textprops,
            wedgeprops=dict(width=0.5),
            pctdistance=0.75
        )
    ax[1,2].pie(df['g'].value_counts(),
            colors=colors,
            autopct = '%1.1f%%',
            textprops=textprops,
            wedgeprops=dict(width=0.5),
            pctdistance=0.75
        )

    ax[0,0].set_title('b',fontsize=10)
    ax[0,1].set_title('c',fontsize=10)
    ax[0,2].set_title('d',fontsize=10)
    ax[1,0].set_title('e',fontsize=10)
    ax[1,1].set_title('f',fontsize=10)
    ax[1,2].set_title('g',fontsize=10)
    fig.legend(labels,
            loc=4,                
            fontsize=7
            )
    plt.suptitle('Como estan distribuidas tus ventas')
    fig.tight_layout()
    plt.savefig(f'orders3.png',dpi=600,transparent=True)

结果是: enter image description here


Tags: nodfvalueaxwidthdictcolorspie
2条回答
  • 如果直接使用^{}绘制数据帧,则颜色将得到正确管理。
    • 选择要打印的特定列:dfc[['b', 'c', 'd', 'e', 'f', 'g']].plot.pie(...)
  • 使用^{}将数据帧从宽转换为长
  • 使用^{}获取每个组的值计数
    • dfc显示所有值,即使是0,这与使用^{}不同。这将确保每个组的颜色始终正确应用
  • 使用autopct='%1.1f%%'autopct = lambda v: f'{v:.1f}%' if v > 0 else None格式化楔形标签。第二个选项不会添加标签,除非值为>0
# display(dfc)
variable  a  b  c  d  e  f  g
value                        
NO        0  3  5  2  3  0  4
SI        5  2  0  3  2  5  1
  • 这通过消除冗余大大减少了代码库
  • pandas 1.3.2matplotlib 3.4.2
import pandas as pd
from matplotlib.patches import Patch

# used df from the OP

def pieplotstest(df):
    colors=["#172a3d", "#e33e31"]
    textprops=dict(color="w", weight='bold', size=9)
    labels=['NO','SI']

    # convert the dataframe from wide to long
    dfm = df.melt()

    # get the counts for each group
    dfc = pd.crosstab(dfm.value, dfm.variable)

    # format the percent value to be None if the value is not greater than 0
    autopct = lambda v: f'{v:.1f}%' if v > 0 else None

    # plot the dataframe directly
    axes = dfc.plot.pie(subplots=True, layout=(2, 4), colors=colors,
                        autopct=autopct, figsize=(10, 6), textprops=textprops,
                        wedgeprops=dict(width=0.5), pctdistance=0.7, legend=False)

    # flatten the array of axes
    axes = axes.ravel()

    # extract the figure object
    fig = axes[0].get_figure()

    # rotate the label
    for ax in axes:
        yl = ax.get_ylabel()
        ax.set_ylabel(yl, rotation=0, fontsize=12)

    # create the legend
    legend_elements = [Patch(fc=c, label=l) for c, l in zip(colors, labels)]
    fig.legend(handles=legend_elements, loc=4, fontsize=12, bbox_to_anchor=(.95, .2))

    fig.tight_layout()
    fig.suptitle('Como estan distribuidas tus ventas')
    fig.savefig(f'orders3.png',dpi=600,transparent=True)


pieplotstest(df)

enter image description here

因此,注释者是正确的,当只有一个值带有value_counts()时,您会遇到问题

因此,我将DF转换为:

df = df.T.apply(pd.Series.value_counts, axis=1).fillna(0).reset_index()
df.columns = ('question', 'no', 'si')

创建了使代码更清晰所需的子批次索引列表:

subplot_list = []
for i in range(2):
    for j in range(3):
        subplot_list.append([i,j])

并添加了一个循环来遍历每个问题(问题为“a”、“b”等):

    for index, row in new_df.iterrows():
        if row['question'] == 'a':
            pass
        else:
            current_sub = subplot_list[index-1]
            row_num = current_sub[0]
            column = current_sub[1]

            ax[row_num,column].pie(
                [row['no'], row['si']],
                colors=colors,
                autopct = '%1.1f%%',
                textprops=textprops,
                wedgeprops=dict(width=0.5),
                pctdistance=0.7
            )

            ax[row_num,column].set_title(row['question'],fontsize=10)

输出的完整代码如下所示:

import pandas as pd
import matplotlib.pyplot as plt


colnames=['a','b','c','d','e','f','g']
values=[
    ['SI','SI','NO','SI','SI','SI','NO'],
    ['SI','NO','NO','SI','NO','SI','NO'],
    ['SI','SI','NO','SI','SI','SI','NO'],
    ['SI','NO','NO','NO','NO','SI','SI'],
    ['SI','NO','NO','NO','NO','SI','NO']]

df=pd.DataFrame(values,columns=colnames)

df = df.T.apply(pd.Series.value_counts, axis=1).fillna(0).reset_index()
df.columns = ('question', 'no', 'si')

subplot_list = []
for i in range(2):
    for j in range(3):
        subplot_list.append([i,j])

def pieplotstest(df):
    fig,ax =plt.subplots(2,3,facecolor=(1, 1, 1),figsize=(7.2,4.3))
    plt.style.use('fivethirtyeight')

    colors=["#172a3d","#e33e31"]
    textprops=dict(color="w",weight='bold',size=5)
    labels=['NO','SI']


    for index, row in new_df.iterrows():
        if row['question'] == 'a':
            pass
        else:
            current_sub = subplot_list[index-1]
            row_num = current_sub[0]
            column = current_sub[1]

            ax[row_num,column].pie(
                [row['no'], row['si']],
                colors=colors,
                autopct = '%1.1f%%',
                textprops=textprops,
                wedgeprops=dict(width=0.5),
                pctdistance=0.7
            )

            ax[row_num,column].set_title(row['question'],fontsize=10)

    fig.legend(labels,
            loc=4,                
            fontsize=7
            )
    plt.suptitle('Como estan distribuidas tus ventas')
    plt.savefig(f'orders3.png',dpi=600,transparent=True)

Pie chart in a loop

相关问题 更多 >

    热门问题