水平条形图,每个索引框中有子图的图表。

huangapple go评论102阅读模式
英文:

Chart with horizontal bar subcharts for each index bin in dataframe

问题

我有一个带有多级索引的数据框(按“5分钟间隔”和“价格”索引排序)。

我知道使用df.plot.barh()可以创建简单的水平条形图。此外,我可以通过以下方式遍历数据框,按“5分钟间隔”索引分组:

  1. for date in df.index.levels[0]:
  2. print(df.loc[date])

并获取每个“5分钟间隔”索引的数据框,如下所示:

  1. quantity
  2. price
  3. 172.20 330
  4. 172.19 1

是否有一种方法可以使用matplotlib创建一个图表,其中每个“5分钟间隔”索引都是水平条形图?在示意图中,它的外观如下所示:

水平条形图,每个索引框中有子图的图表。

英文:

I have dataframe with multi-index (sorted by "5min_intervals" and "price" indexes).

  1. quantity
  2. 5min_intervals price
  3. 2023-07-27 17:40:00 172.20 330
  4. 172.19 1
  5. 2023-07-27 17:45:00 172.25 4
  6. 172.24 59
  7. 172.23 101
  8. 172.22 224
  9. 172.21 64
  10. 172.20 303
  11. 172.19 740
  12. 172.18 26
  13. 2023-07-27 17:50:00 172.17 30
  14. 172.16 2
  15. 172.15 1014
  16. 172.14 781
  17. 172.13 1285

I know about simple horizontal bar chart with df.plot.barh(). Also I can iterate dataframe by '5min_intervals' index with

  1. for date in df.index.levels[0]:
  2. print(df.loc[date])

and get dataframes for each '5min_intervals' index like below

  1. quantity
  2. price
  3. 172.20 330
  4. 172.19 1

Is there any way to create one chart with matplotlib where for each '5min_intervals' index would be horizontal bar chart. Schematically it looks like in below picture 水平条形图,每个索引框中有子图的图表。

答案1

得分: 1

以下是翻译好的代码部分:

  1. # 让我们准备一些虚拟数据来工作:
  2. from pandas import DataFrame, Timestamp
  3. data = {
  4. 'quantity': {
  5. (Timestamp('2023-07-27 17:40:00'), 172.2): 330,
  6. (Timestamp('2023-07-27 17:40:00'), 172.19): 1,
  7. (Timestamp('2023-07-27 17:45:00'), 172.25): 4,
  8. (Timestamp('2023-07-27 17:45:00'), 172.24): 59,
  9. (Timestamp('2023-07-27 17:45:00'), 172.23): 101,
  10. (Timestamp('2023-07-27 17:45:00'), 172.22): 224,
  11. (Timestamp('2023-07-27 17:45:00'), 172.21): 64,
  12. (Timestamp('2023-07-27 17:45:00'), 172.2): 303,
  13. (Timestamp('2023-07-27 17:45:00'), 172.19): 740,
  14. (Timestamp('2023-07-27 17:45:00'), 172.18): 26,
  15. (Timestamp('2023-07-27 17:50:00'), 172.17): 30,
  16. (Timestamp('2023-07-27 17:50:00'), 172.16): 2,
  17. (Timestamp('2023-07-27 17:50:00'), 172.15): 1014,
  18. (Timestamp('2023-07-27 17:50:00'), 172.14): 781,
  19. (Timestamp('2023-07-27 17:50:00'), 172.13): 1285
  20. }
  21. }
  22. df = DataFrame(data)
  1. # 关于图形,几乎没有像您要求的那样准备好的东西。因此,我们需要手动构建它。首先,让我们进行一些基本的准备:
  2. unique_time = df.index.get_level_values(0).unique().sort_values()
  3. unique_price = df.index.get_level_values(1).unique().sort_values()
  4. spacing = 0.2 # 两个连续水平线之间的最小距离
  5. values = (1-spacing) * df/df.max() # 水平线的相对长度
  6. base = DataFrame(index=unique_price) # 带有价格的最宽的空白框架
  1. # 要构建图形,我们可以使用`barh(y, width, height, left)` - 水平条形图 - 价格作为第一个参数,时间作为左移,宽度位置放置值,以及一些固定的小高度。为了使非常小的值可见,我们还可以使用`barh`再次标记线的开始(左端)的地方,使用小刻度。
  2. import matplotlib.pyplot as plt
  3. from matplotlib.colors import TABLEAU_COLORS
  4. from itertools import cycle
  5. fig, ax = plt.subplots(figsize=(7,7))
  6. xlabels = unique_time.astype(str)
  7. ylabels = unique_price.astype(str)
  8. ax.set_xticks(range(len(xlabels)), xlabels, rotation=45)
  9. ax.set_yticks(range(len(ylabels)), ylabels)
  10. ax.set_xlim([-0.5,len(xlabels)])
  11. ax.set_ylim([-1, len(ylabels)])
  12. for i, (t, c) in enumerate(zip(unique_time, cycle(TABLEAU_COLORS))):
  13. pr = base.join(values.loc[t]).squeeze()
  14. # 绘制水平线,左移i个时间点
  15. ax.barh(ylabels, pr, 0.1, i, color=c)
  16. # 在线的左端即它们的开始处放置刻度
  17. ax.barh(ylabels, 0.01*pr.notna(), 0.3, i, color=c)
  18. ax.grid(axis='y', linestyle='--', linewidth=0.5)
  19. fig.tight_layout()
  20. plt.show()

这是代码的翻译部分。如果您有其他问题或需要进一步的帮助,请随时提出。

英文:

Let's prepare some dummy data to work with:

  1. from pandas import DataFrame, Timestamp
  2. data = {
  3. 'quantity': {
  4. (Timestamp('2023-07-27 17:40:00'), 172.2): 330,
  5. (Timestamp('2023-07-27 17:40:00'), 172.19): 1,
  6. (Timestamp('2023-07-27 17:45:00'), 172.25): 4,
  7. (Timestamp('2023-07-27 17:45:00'), 172.24): 59,
  8. (Timestamp('2023-07-27 17:45:00'), 172.23): 101,
  9. (Timestamp('2023-07-27 17:45:00'), 172.22): 224,
  10. (Timestamp('2023-07-27 17:45:00'), 172.21): 64,
  11. (Timestamp('2023-07-27 17:45:00'), 172.2): 303,
  12. (Timestamp('2023-07-27 17:45:00'), 172.19): 740,
  13. (Timestamp('2023-07-27 17:45:00'), 172.18): 26,
  14. (Timestamp('2023-07-27 17:50:00'), 172.17): 30,
  15. (Timestamp('2023-07-27 17:50:00'), 172.16): 2,
  16. (Timestamp('2023-07-27 17:50:00'), 172.15): 1014,
  17. (Timestamp('2023-07-27 17:50:00'), 172.14): 781,
  18. (Timestamp('2023-07-27 17:50:00'), 172.13): 1285
  19. }
  20. }
  21. df = DataFrame(data)

As for the graphics, there's hardly anything like you asked ready from the box. So we need to build it manually. At first, let's do some basic preparation:

  1. unique_time = df.index.get_level_values(0).unique().sort_values()
  2. unique_price = df.index.get_level_values(1).unique().sort_values()
  3. spacing = 0.2 # a minimum distance between two consecutive horizontal lines
  4. values = (1-spacing) * df/df.max() # relative lengths of horizontal lines
  5. base = DataFrame(index=unique_price) # the widest blank frame with prices

To build the graphics, we can use barh(y, width, height, left) - horizontal bar - with prices as the first parameter, time as left shifting, values in place of width, and some fixed small height. To make very small values visible, we can additionally mark the beginning (left end) of a line with a small tick using barh again.

  1. import matplotlib.pyplot as plt
  2. from matplotlib.colors import TABLEAU_COLORS
  3. from itertools import cycle
  4. fig, ax = plt.subplots(figsize=(7,7))
  5. xlabels = unique_time.astype(str)
  6. ylabels = unique_price.astype(str)
  7. ax.set_xticks(range(len(xlabels)), xlabels, rotation=45)
  8. ax.set_yticks(range(len(ylabels)), ylabels)
  9. ax.set_xlim([-0.5,len(xlabels)])
  10. ax.set_ylim([-1, len(ylabels)])
  11. for i, (t, c) in enumerate(zip(unique_time, cycle(TABLEAU_COLORS))):
  12. pr = base.join(values.loc[t]).squeeze()
  13. # draw horizontal lines, shifted left by i-th timepoint
  14. ax.barh(ylabels, pr, 0.1, i, color=c)
  15. # put tics at the left end of lines, i.e. their beginning
  16. ax.barh(ylabels, 0.01*pr.notna(), 0.3, i, color=c)
  17. ax.grid(axis='y', linestyle='--', linewidth=0.5)
  18. fig.tight_layout()
  19. plt.show()

And here's the output:
水平条形图,每个索引框中有子图的图表。


  1. python : 3.11
  2. pandas : 1.5.1
  3. matplotlib : 3.6.1

huangapple
  • 本文由 发表于 2023年7月28日 03:38:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76782915.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定