如何用字数和列名注释堆积的条形图?

时间:2020-06-07 00:09:13

标签: python pandas matplotlib seaborn

我的问题是关于在堆积的条形图中绘制单词频率,而不是条上带有标签的数字。 假设我有这些话

Date    Text     Count
01/01/2020  cura    25
           destra   24
             fino   18
            guerra  13
        americani   13
02/01/2020  italia  137
            turismo 112
            nuovi   109
             pizza  84
            moda    79

通过按日期分组并按Text汇总创建,然后选择前5个(head(5)):

尝试:

(我的尝试:这会生成堆积图,但是颜色和标签不是我想要的)

data.groupby('Date').agg({'Text': 'value_counts'}).rename(columns={'Text': 'Count'}).groupby('Date').head(5).unstack().plot(kind='bar', stacked=True)

请求: 我的预期输出将是条形图,其中在x轴上有日期,在y轴上有单词频率(在同一日期的每个单词都应以不同的方式着色,例如在堆积图中,并且每个条形都应显示单词及其频率)。

示例: 请在下面看到一个堆积图的示例,它将有助于解释我想做的事情(如果可能)。 在栏中,我想用上面的代码选择上面单词的名称和频率,而不是数字(340、226,...)。在x轴上会显示我之前显示给您的日期,而不是年份(我在网上找不到更好的图表)。第一个栏显示了前4个字(应为5个字,但我只找到了一个包含4组的条形图),以及如何显示结果。 关于图表的大小,您能记住我有200个日期吗?对显示图表很有用。

如果您想向我展示如何做到这一点,即使使用另一个数据集,也很好。非常感谢您花时间帮助我。 enter image description here

1 个答案:

答案 0 :(得分:0)

创建数据框

import pandas as pd
import matplotlib.pyplot as plt

# data and dataframe
data = {'Date': ['01/01/2020', '01/01/2020', '01/01/2020', '02/01/2020', '02/01/2020', '02/01/2020'],
        'Text': [['cura']*25, ['destra']*24, ['fino']*18, ['italia']*137, ['turismo']*112, ['nuovi']*109]}

df = pd.DataFrame(data)

df = df.explode('Text')

df.Date = pd.to_datetime(df.Date)

groupby并作图

  • 为了绘制单词,请注意,每个日期行都有所有单词作为列。
  • 即使某些单词的计数为0,绘图API仍包含该信息
  • api绘制所有日期的第一列,然后绘制所有日期的下列,依此类推。
  • 因此,用于文本注释的cols列表必须使每个单词重复df_gb中存在的日期。
  • 如果您需要使用head(),请将以下行替换为df_gb
    • df_gb = df.groupby('Date').agg({'Text': 'value_counts'}).rename(columns={'Text': 'Count'}).groupby('Date').head(2).unstack()
df_gb = df.groupby(['Date']).agg({'Text': 'value_counts'}).rename(columns={'Text': 'Count'}).unstack('Text')

print(df_gb)

           Count                                   
Text        cura destra  fino italia  nuovi turismo
Date                                               
2020-01-01  25.0   24.0  18.0    NaN    NaN     NaN
2020-02-01   NaN    NaN   NaN  137.0  109.0   112.0

# create list of words of appropriate length; all words repeat for each date
cols = [x[1] for x in df_gb.columns for _ in range(len(df_gb))]

# plot df_gb
ax = df_gb.plot.bar(stacked=True)

# annotate the bars
for i, rect in enumerate(ax.patches):
    # Find where everything is located
    height = rect.get_height()
    width = rect.get_width()
    x = rect.get_x()
    y = rect.get_y()

    # The height of the bar is the count value and can used as the label
    label_text = f'{height:.0f}: {cols[i]}'

    label_x = x + width / 2
    label_y = y + height / 2

    # don't include label if it's equivalently 0
    if height > 0.001:
        ax.text(label_x, label_y, label_text, ha='center', va='center', fontsize=8)

# rename xtick labels; remove time
ticks, labels = plt.xticks(rotation=90)
labels = [label.get_text()[:10] for label in labels]
plt.xticks(ticks=ticks, labels=labels)

ax.get_legend().remove()
plt.show()

enter image description here