python - 具有数字线间距分布的 Seaborn 条形图
问题描述
我想制作一个具有数字线型间距的条形图。
所以如果我们有这样的数据:
d = {'Avg_Price': [22.1, 19.98, 24.4, 24.4, 12.0, 41.98, 12.0, 35.0, 25.84, 25.0, 60.0],
'estimated_purchasers': [2796.9999999999995, 1000.0, 672.98, 672.98, 335.0, 299.0, 500.0, 104.22, 42.96, 500.0, 225.0]}
revenues = pd.DataFrame(data=d)
这只是一个基本的条形图:
ax = sns.barplot(x='Avg_Price',
y='estimated_purchasers',
data=revenues)
我希望它像数字线一样间隔(所以让我们从 0 到 60 等距) - 更像这样:
我可能完全想多了,但我该怎么做呢?
解决方案
您遇到的最大问题是 aseaborn
自动将条形图转换为具有分类的 x 轴。因此,seaborn 不是真正的数字位置,而是将您的 x 轴重新采样到 0 - (唯一 x 值的数量)的范围内,然后用该类别的字符串表示形式标记它们。要实现您想要的情节,您可以
- 使用 seaborn 实现一个解决方法来修复 x 轴范围,并将绘制的矩形移动到适当的位置(这需要对 matplotlib 有一些深入的了解)
import seaborn as sns
import matplotlib.pyplot as plt
sns.set() # invoke seaborn styling
# manually making axes to make a wider plot for viewing
fig, ax = plt.subplots(figsize=(12, 4))
ax = sns.barplot(x='Avg_Price',
y='estimated_purchasers',
data=revenues)
# Get all unique x-values in ascending order
x_values = sorted(revenues["Avg_Price"].unique())
# New xlim spans from -1 to [max(x_values) + 1]
ax.set_xlim(-1, x_values[-1] + 1)
# a barplot w/ error bars are rectangles (patches) & lines
# so we fetch all artists related to these to update their position on the Axes
artists = zip(ax.patches, ax.lines)
for x_val, (rect, err_line) in zip(x_values, artists):
# ensure everything is centered on the x_val
new_rect_x = x_val - (rect.get_width() / 2)
rect.set_x(new_rect_x)
err_line.set_xdata([x_val, x_val])
# Take care to update the x-axis itself
new_xticks = [0, 30, 60]
ax.set_xticks(new_xticks)
ax.set_xticklabels(new_xticks)
在这种情况下,我首选的解决方案是一起跳过 seaborn
- 通过 matplotlib 自己绘制绘图
import seaborn as sns
import matplotlib.pyplot as plt
sns.set() # invoke seaborn styling
# Perform data aggregation explicitly instead of relying on seaborn
agg_rev = (
revenues.groupby("Avg_Price")["estimated_purchasers"]
.agg(["mean", "sem"])
.reset_index()
)
agg_rev["sem"] = agg_rev["sem"].fillna(0)
# Now we can plot :)
fig, ax = plt.subplots(figsize=(12, 4))
ax.bar(x="Avg_Price", height="mean", data=agg_rev)
ax.errorbar(x="Avg_Price", y="mean", yerr="sem", data=agg_rev, fmt="none", ecolor="black")
ax.set_xticks([0, 30, 60])
ax.set_xlabel("Avg Price")
ax.set_ylabel("estimated_purchases")
ax.grid(False, axis="x") # turn off vertical gird lines b/c they look silly
推荐阅读
- php - 使用 Eloquent 查询相关记录
- google-sheets - 使用随机不重复的行重复多列
- android-studio - 使用 kotlin 在 android 中创建自定义微调器适配器
- python - 使用 tweetpy 获取转发者的数量
- typescript - 定义返回接口的函数时,Typescript 的行为似乎不一致
- r - 计算数据框的 2 个元素之间的距离
- java - 如何将自定义按钮添加到工具栏
- python - 检查是否不在列表中 - Python 中的更多条件
- c++ - posix_spawn 创建一个僵尸进程并返回成功
- terraform - 我可以使用 terraform 将开箱即用的 aws_iam_policy (SecurityAudit)、帐户 ID 和外部 ID 添加到 aws_iam_role 吗?