matplotlib 如何将背景颜色从折线图添加到折线图的线段

zi8p0yeb  于 2023-10-24  发布在  其他
关注(0)|答案(1)|浏览(145)

我有一个框架如下,并希望得到一个情节与线和背景颜色要么红色或白色(取决于颜色的值_var)。

  1. line_var color_var
  2. datetime
  3. 2023-04-20 13:45 3 1
  4. 2023-04-20 14:00 4 0
  5. 2023-04-20 15:00 5 0
  6. 2023-04-20 15:15 4 1
  7. 2023-04-20 15:45 3 1
  8. 2023-04-20 16:00 5 1
  9. 2023-04-20 16:45 6 0
  10. 2023-04-20 17:45 7 0
  11. 2023-04-20 18:00 5 0
  12. 2023-04-20 18:45 6 1
  13. 2023-04-20 19:45 8 1
  14. 2023-04-21 13:45 9 0

下面的代码

  1. import pandas as pd
  2. import numpy as np
  3. from matplotlib import dates as mdates
  4. from matplotlib.colors import ListedColormap
  5. import matplotlib.pyplot as plt
  6. df = pd.DataFrame({'datetime':['2023-04-20 13:45','2023-04-20 14:00','2023-04-20 15:00',
  7. '2023-04-20 15:15','2023-04-20 15:45','2023-04-20 16:00','2023-04-20 16:45','2023-04-20 17:45','2023-04-20 18:00','2023-04-20 18:45','2023-04-20 19:45','2023-04-21 13:45'],
  8. 'line_var':[3,4,5,4,3,5,6,7,5,6,8,9],
  9. 'color_var':[1,0,0,1,1,1,0,0,0,1,1,0]})
  10. df = df.assign(datetime=pd.to_datetime(df.datetime))
  11. df = df.set_index('datetime')
  12. cmap = ListedColormap(['white','red'])
  13. fig = plt.figure(figsize=(50,10))
  14. ax = fig.add_subplot()
  15. ax.plot(df['line_var'])
  16. ax.set_xlabel('')
  17. plt.xticks(rotation = 30)
  18. ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
  19. #this gives an error
  20. ax.pcolor(df.index, ax.get_ylim(),
  21. df['color_var'].values[np.newaxis].T,
  22. cmap = cmap, alpha = 0.4,
  23. linewidth=0, antialiased=True, shading='nearest')
  24. plt.axhline(y = 0, color = 'black')
  25. plt.tight_layout()

抛出错误

  1. ---------------------------------------------------------------------------
  2. TypeError Traceback (most recent call last)
  3. Cell In[21], line 21
  4. 18 ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
  5. 20 #this gives an error
  6. ---> 21 ax.pcolor(df.index, ax.get_ylim(),
  7. 22 df['color_var'].values[np.newaxis].T,
  8. 23 cmap = cmap, alpha = 0.4,
  9. 24 linewidth=0, antialiased=True, shading='nearest')
  10. 25 plt.axhline(y = 0, color = 'black')
  11. 26 plt.tight_layout()
  12. File ~\anaconda3\envs\py11\Lib\site-packages\matplotlib\__init__.py:1442, in _preprocess_data.<locals>.inner(ax, data, *args, **kwargs)
  13. 1439 @functools.wraps(func)
  14. 1440 def inner(ax, *args, data=None, **kwargs):
  15. 1441 if data is None:
  16. -> 1442 return func(ax, *map(sanitize_sequence, args), **kwargs)
  17. 1444 bound = new_sig.bind(ax, *args, **kwargs)
  18. 1445 auto_label = (bound.arguments.get(label_namer)
  19. 1446 or bound.kwargs.get(label_namer))
  20. File ~\anaconda3\envs\py11\Lib\site-packages\matplotlib\axes\_axes.py:5946, in Axes.pcolor(self, shading, alpha, norm, cmap, vmin, vmax, *args, **kwargs)
  21. 5944 shading = mpl.rcParams['pcolor.shading']
  22. 5945 shading = shading.lower()
  23. -> 5946 X, Y, C, shading = self._pcolorargs('pcolor', *args, shading=shading,
  24. 5947 kwargs=kwargs)
  25. 5948 Ny, Nx = X.shape
  26. 5950 # convert to MA, if necessary.
  27. File ~\anaconda3\envs\py11\Lib\site-packages\matplotlib\axes\_axes.py:5757, in Axes._pcolorargs(self, funcname, shading, *args, **kwargs)
  28. 5755 else: # ['nearest', 'gouraud']:
  29. 5756 if (Nx, Ny) != (ncols, nrows):
  30. -> 5757 raise TypeError('Dimensions of C %s are incompatible with'
  31. 5758 ' X (%d) and/or Y (%d); see help(%s)' % (
  32. 5759 C.shape, Nx, Ny, funcname))
  33. 5760 if shading == 'nearest':
  34. 5761 # grid is specified at the center, so define corners
  35. 5762 # at the midpoints between the grid centers and then use the
  36. 5763 # flat algorithm.
  37. 5764 def _interp_grid(X):
  38. 5765 # helper for below
  39. TypeError: Dimensions of C (12, 1) are incompatible with X (12) and/or Y (2); see help(pcolor)

我在这里读到Numpy pcolormesh: TypeError: Dimensions of C are incompatible with X and/or Y,我应该转置我的数组,但它不起作用,或者我没有正确地这样做。

bn31dyow

bn31dyow1#

matplotlib的pcolor函数期望X、Y和C参数在特定的维度上,以在图中阴影区域。您遇到的问题是X、Y和C数组的维度不匹配。
当你为X提供df.index,为Y提供ax.get_ylim()时,你基本上是告诉pcolor考虑尺寸为(12,2)的矩形网格,因为df.index的长度为12,ax.get_ylim()的长度为2。
但是,df['color_var'].values[np.newaxis].T提供的C数组(颜色数据)的形状是(12,1),这与前面提到的网格不兼容。
解决这个问题的一种方法是将X和Y数组网格化以创建所需的网格,然后扩展C数组以匹配此网格的形状。

  1. import pandas as pd
  2. import numpy as np
  3. from matplotlib import dates as mdates
  4. from matplotlib.colors import ListedColormap
  5. import matplotlib.pyplot as plt
  6. df = pd.DataFrame({
  7. 'datetime': ['2023-04-20 13:45', '2023-04-20 14:00', '2023-04-20 15:00',
  8. '2023-04-20 15:15', '2023-04-20 15:45', '2023-04-20 16:00',
  9. '2023-04-20 16:45', '2023-04-20 17:45', '2023-04-20 18:00',
  10. '2023-04-20 18:45', '2023-04-20 19:45', '2023-04-21 13:45'],
  11. 'line_var': [3, 4, 5, 4, 3, 5, 6, 7, 5, 6, 8, 9],
  12. 'color_var': [1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0]
  13. })
  14. df = df.assign(datetime=pd.to_datetime(df.datetime))
  15. df = df.set_index('datetime')
  16. fig, ax = plt.subplots(figsize=(10, 6))
  17. # Plot the line
  18. ax.plot(df['line_var'], color='blue')
  19. # Fill background color based on color_var values
  20. for i in range(1, len(df)):
  21. if df['color_var'].iloc[i] == 1:
  22. ax.fill_between([df.index[i-1], df.index[i]], y1=ax.get_ylim()[0], y2=ax.get_ylim()[1], color='red', alpha=0.4)
  23. plt.xticks(rotation=30)
  24. ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
  25. plt.axhline(y=0, color='black')
  26. plt.tight_layout()
  27. plt.show()

更新:

  1. import pandas as pd
  2. import numpy as np
  3. from matplotlib import dates as mdates
  4. import matplotlib.pyplot as plt
  5. df = pd.DataFrame({
  6. 'datetime': ['2023-04-20 13:45', '2023-04-20 14:00', '2023-04-20 15:00',
  7. '2023-04-20 15:15', '2023-04-20 15:45', '2023-04-20 16:00',
  8. '2023-04-20 16:45', '2023-04-20 17:45', '2023-04-20 18:00',
  9. '2023-04-20 18:45', '2023-04-20 19:45', '2023-04-21 13:45'],
  10. 'line_var': [3, 4, 5, 4, 3, 5, 6, 7, 5, 6, 8, 9],
  11. 'color_var': [1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0]
  12. })
  13. df = df.assign(datetime=pd.to_datetime(df.datetime))
  14. df = df.set_index('datetime')
  15. fig, ax = plt.subplots(figsize=(10, 6))
  16. # Plot the line
  17. ax.plot(df['line_var'], color='blue')
  18. # Fill background color based on color_var values
  19. start_fill = None
  20. for i, (timestamp, value) in enumerate(df['color_var'].items()):
  21. if value == 1 and start_fill is None:
  22. start_fill = timestamp
  23. elif value == 0 and start_fill is not None:
  24. ax.fill_between([start_fill, timestamp], y1=ax.get_ylim()[0], y2=ax.get_ylim()[1], color='red', alpha=0.4)
  25. start_fill = None
  26. # Handling the case if the last value in color_var is 1
  27. if start_fill is not None:
  28. ax.fill_between([start_fill, df.index[-1]], y1=ax.get_ylim()[0], y2=ax.get_ylim()[1], color='red', alpha=0.4)
  29. plt.xticks(rotation=30)
  30. ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
  31. plt.axhline(y=0, color='black')
  32. plt.tight_layout()
  33. plt.show()

展开查看全部

相关问题