对齐线和分组的条形图

发布于 2025-01-23 06:33:33 字数 3465 浏览 3 评论 0原文

我正在尝试使用Python的Pandas库在条形图的顶部绘制线路图。条形图是来自数据框的集群图表,当本身绘制时看起来像:

clustered bar Chart

线图是整个数据集上的平均值:

line图表

我可以成功地绘制两者如果使用所有线路图,则在同一轴对象上的数据集:

所有线图

但是当我 切换群集条的数据帧实际使用条形图,并将其与线路图一起绘制,线图希望从第二个索引位置绘制,从而导致偏移。

bar and and cat and offset

这个问题对Matplotlib对bar和line的X轴的方式有一个有趣的评论图表,这可能在这里很重要,但是我无法弄清该如何处理该见解。

解决这个路线问题的好方法是什么?

复制的代码:

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

table_data = {2019: {1: np.nan,
2: np.nan,
3: np.nan,
  4: 1.4200000000000002,
  5: 0.8193548387096775,
  6: 1.420689655172414,
  7: 0.4645161290322581,
  8: 0.10322580645161289,
  9: 0.29333333333333333,
  10: 1.7741935483870968,
  11: 0.32,
  12: 6.703225806451614},
 2020: {1: 5.52,
  2: 12.613793103448277,
  3: 0.9428571428571428,
  4: 0.1793103448275862,
  5: 0.39354838709677414,
  6: 1.3866666666666667,
  7: 1.9800000000000002,
  8: 0.6689655172413793,
  9: 0.19333333333333336,
  10: 5.896774193548388,
  11: 0.6896551724137931,
  12: 4.103225806451613},
 2021: {1: 2.7935483870967746,
  2: 5.15,
  3: 9.696774193548388,
  4: 3.74,
  5: 2.8967741935483873,
  6: 0.9103448275862069,
  7: 1.6516129032258065,
  8: 0.3,
  9: 0.38571428571428573,
  10: 5.141935483870968,
  11: 8.58,
  12: 6.052173913043479},
 2022: {1: 2.3923076923076922,
  2: 31.678571428571427,
  3: 8.761290322580646,
  4: np.nan,
  5: np.nan,
  6: np.nan,
  7: np.nan,
  8: np.nan,
  9: np.nan,
  10: np.nan,
  11: np.nan,
  12: np.nan}}

means = {1: 3.6137931034482755,
 2: 16.435294117647057,
 3: 7.132530120481928,
 4: 1.797752808988764,
 5: 1.3698924731182796,
 6: 1.240909090909091,
 7: 1.358695652173913,
 8: 0.3522727272727273,
 9: 0.28863636363636364,
 10: 4.2709677419354835,
 11: 3.2247191011235956,
 12: 5.578823529411765}

df_bars = pd.DataFrame(table_data)
df_means = pd.DataFrame.from_dict(means, orient = 'index', columns = ['Mean'])

# Clustered bar chart by itself
df_bars.plot(kind = 'bar',
           title = 'Average Daily Rainfall by Month',
           ylabel = 'Average Daily Rainfall (mm)',
           figsize = (10, 6)
          )

# Line chart by itself
df_means.plot(
    kind = 'line',
    title = 'Average Daily Rainfall by Month',
    ylabel = 'Average Daily Rainfall (mm)',
    y = 'Mean'
)

# Show all data as line charts. This works OK
ax_avg = df_bars.plot(kind = 'line',
           title = 'Average Daily Rainfall by Month',
           ylabel = 'Average Daily Rainfall (mm)',
           figsize = (10, 6)
          )

df_means.plot(
    ax = ax_avg,
    kind = 'line',
    y = 'Mean'
)
plt.show()

# Show bar data and line chart on the one plot. The line chart is offset!
ax_avg2 = df_bars.plot(kind = 'bar',
           title = 'Average Daily Rainfall by Month',
           ylabel = 'Average Daily Rainfall (mm)',
           figsize = (10, 6)
          )

df_means.plot(
    ax = ax_avg2,
    kind = 'line',
    y = 'Mean'
)
plt.show()

I am trying to plot a line chart on top of a bar chart using Python's pandas library. The bar chart is a clustered chart from a DataFrame and looks like so when plotted by itself:

Clustered Bar Chart

The line chart is the averages across the whole dataset:

Line Chart

I can successfully plot both sets of data on the same axis object if using all line charts:

All Line Charts

But when I switch the DataFrame for the clustered bar to actually using a bar chart and plot it along with the line chart, the line chart wants to plot from the second index position, leading to an offset.

Bar and Line With Offset

The answer to this question has an interesting comment about the way matplotlib treats the x-axis for both bar and line charts, which may be relevant here, but I can't work out what to do with that insight.

What's a good way to fix this alignment issue?

Code to reproduce:

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

table_data = {2019: {1: np.nan,
2: np.nan,
3: np.nan,
  4: 1.4200000000000002,
  5: 0.8193548387096775,
  6: 1.420689655172414,
  7: 0.4645161290322581,
  8: 0.10322580645161289,
  9: 0.29333333333333333,
  10: 1.7741935483870968,
  11: 0.32,
  12: 6.703225806451614},
 2020: {1: 5.52,
  2: 12.613793103448277,
  3: 0.9428571428571428,
  4: 0.1793103448275862,
  5: 0.39354838709677414,
  6: 1.3866666666666667,
  7: 1.9800000000000002,
  8: 0.6689655172413793,
  9: 0.19333333333333336,
  10: 5.896774193548388,
  11: 0.6896551724137931,
  12: 4.103225806451613},
 2021: {1: 2.7935483870967746,
  2: 5.15,
  3: 9.696774193548388,
  4: 3.74,
  5: 2.8967741935483873,
  6: 0.9103448275862069,
  7: 1.6516129032258065,
  8: 0.3,
  9: 0.38571428571428573,
  10: 5.141935483870968,
  11: 8.58,
  12: 6.052173913043479},
 2022: {1: 2.3923076923076922,
  2: 31.678571428571427,
  3: 8.761290322580646,
  4: np.nan,
  5: np.nan,
  6: np.nan,
  7: np.nan,
  8: np.nan,
  9: np.nan,
  10: np.nan,
  11: np.nan,
  12: np.nan}}

means = {1: 3.6137931034482755,
 2: 16.435294117647057,
 3: 7.132530120481928,
 4: 1.797752808988764,
 5: 1.3698924731182796,
 6: 1.240909090909091,
 7: 1.358695652173913,
 8: 0.3522727272727273,
 9: 0.28863636363636364,
 10: 4.2709677419354835,
 11: 3.2247191011235956,
 12: 5.578823529411765}

df_bars = pd.DataFrame(table_data)
df_means = pd.DataFrame.from_dict(means, orient = 'index', columns = ['Mean'])

# Clustered bar chart by itself
df_bars.plot(kind = 'bar',
           title = 'Average Daily Rainfall by Month',
           ylabel = 'Average Daily Rainfall (mm)',
           figsize = (10, 6)
          )

# Line chart by itself
df_means.plot(
    kind = 'line',
    title = 'Average Daily Rainfall by Month',
    ylabel = 'Average Daily Rainfall (mm)',
    y = 'Mean'
)

# Show all data as line charts. This works OK
ax_avg = df_bars.plot(kind = 'line',
           title = 'Average Daily Rainfall by Month',
           ylabel = 'Average Daily Rainfall (mm)',
           figsize = (10, 6)
          )

df_means.plot(
    ax = ax_avg,
    kind = 'line',
    y = 'Mean'
)
plt.show()

# Show bar data and line chart on the one plot. The line chart is offset!
ax_avg2 = df_bars.plot(kind = 'bar',
           title = 'Average Daily Rainfall by Month',
           ylabel = 'Average Daily Rainfall (mm)',
           figsize = (10, 6)
          )

df_means.plot(
    ax = ax_avg2,
    kind = 'line',
    y = 'Mean'
)
plt.show()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

前事休说 2025-01-30 06:33:33

您可以使用reset_index将行数据框架的索引更改为零。

这将允许您的条形与基于零的索引对齐:

ax_avg2 = df_bars.plot(kind = 'bar',
           title = 'Average Daily Rainfall by Month',
           ylabel = 'Average Daily Rainfall (mm)',
           figsize = (10, 6)
          )

df_means.reset_index().plot(
    ax = ax_avg2,
    kind = 'line',
    y = 'Mean'
)

输出:

“在此处输入图像说明”

You can use reset_index to change the indexing of line dataframe back to start with zero.

This will allow your bars to line up with zero-based indexing like this:

ax_avg2 = df_bars.plot(kind = 'bar',
           title = 'Average Daily Rainfall by Month',
           ylabel = 'Average Daily Rainfall (mm)',
           figsize = (10, 6)
          )

df_means.reset_index().plot(
    ax = ax_avg2,
    kind = 'line',
    y = 'Mean'
)

Output:

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文