我的问题是关于在堆积的条形图中绘制单词频率,而不是条上带有标签的数字。 假设我有这些话
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个日期吗?对显示图表很有用。
答案 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
并作图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()