将timestamp设为索引后Matplotlib蜡烛图显示异常,求原因
问题
给定如下DataFrame:
open close high low timestamp 0 17910.25 17902.75 17910.50 17901.75 2024-02-28 20:46:10.628867+00:00 1 17902.50 17901.75 17906.50 17900.50 2024-02-28 20:46:50.270189+00:00 2 17902.25 17904.50 17905.50 17901.25 2024-02-28 20:47:55.031114+00:00 3 17904.75 17907.25 17909.00 17904.50 2024-02-28 20:48:44.114794+00:00 4 17907.25 17910.25 17914.50 17906.75 2024-02-28 20:49:31.424009+00:00 5 17910.25 17912.50 17914.50 17906.00 2024-02-28 20:50:05.337921+00:00 6 17912.75 17909.00 17912.75 17906.50 2024-02-28 20:50:51.489718+00:00 7 17909.00 17908.50 17910.50 17905.50 2024-02-28 20:51:32.629298+00:00 8 17908.75 17899.75 17908.75 17899.25 2024-02-28 20:52:06.190489+00:00 9 17899.50 17900.50 17902.00 17897.50 2024-02-28 20:52:38.421629+00:00 10 17900.25 17900.75 17904.25 17898.75 2024-02-28 20:53:22.651748+00:00 11 17900.25 17898.00 17901.25 17895.50 2024-02-28 20:54:07.124026+00:00 12 17898.00 17895.75 17900.75 17892.00 2024-02-28 20:54:36.208693+00:00 13 17895.75 17897.25 17898.00 17893.75 2024-02-28 20:55:00.171311+00:00 14 17897.25 17902.00 17902.00 17895.75 2024-02-28 20:55:09.389301+00:00 15 17902.00 17905.50 17906.75 17901.00 2024-02-28 20:55:30.245781+00:00 16 17905.25 17905.25 17906.50 17900.75 2024-02-28 20:56:03.837146+00:00 17 17905.25 17909.75 17910.75 17904.75 2024-02-28 20:56:26.466095+00:00 18 17909.75 17916.50 17918.25 17908.50 2024-02-28 20:56:47.284619+00:00 19 17916.25 17911.50 17917.25 17911.50 2024-02-28 20:57:16.248157+00:00 20 17911.50 17913.75 17914.50 17909.25 2024-02-28 20:57:56.980558+00:00 21 17913.50 17916.00 17917.25 17910.00 2024-02-28 20:58:32.008823+00:00 22 17916.00 17916.25 17918.75 17913.50 2024-02-28 20:58:59.908276+00:00 23 17916.25 17915.00 17918.25 17915.00 2024-02-28 20:59:16.061040+00:00 24 17915.00 17911.75 17915.25 17910.00 2024-02-28 20:59:27.103036+00:00
使用以下plotCandles函数可正常绘制蜡烛图:
def plotCandles(df): #df.set_index('timestamp', inplace=True) plt.figure() # "up" dataframe will store the stock_prices # when the closing stock price is greater # than or equal to the opening stock prices up = df[df.close >= df.open] # "down" dataframe will store the stock_prices # when the closing stock price is # lesser than the opening stock prices down = df[df.close < df.open] # When the stock prices have increased, then it # will be represented by green color candlestick col1 = 'green' # When the stock prices have decreased, then it # will be represented by red color candlestick col2 = 'red' # Setting width of candlestick elements width = .3 width2 = .03 # Plotting up prices of the stock plt.bar(up.index, up.close-up.open, width, bottom=up.open, color=col1) plt.bar(up.index, up.high-up.close, width2, bottom=up.close, color=col1) plt.bar(up.index, up.low-up.open, width2, bottom=up.open, color=col1) # Plotting down prices of the stock plt.bar(down.index, down.close-down.open, width, bottom=down.open, color=col2) plt.bar(down.index, down.high-down.open, width2, bottom=down.open, color=col2) plt.bar(down.index, down.low-down.close, width2, bottom=down.close, color=col2) # rotating the x-axis tick labels at 30degree # towards right plt.xticks(rotation=30, ha='right') # show it plt.show()
此时生成的蜡烛图显示正常,但取消注释df.set_index('timestamp', inplace=True)将timestamp设为DataFrame的索引后,Matplotlib生成的蜡烛图显示异常,请问这是什么原因?
原因分析
问题根源在于Matplotlib的plt.bar()对时间类型索引的处理方式:
- 用默认整数索引时,
up.index和down.index是连续的0、1、2...整数,plt.bar()直接把这些整数当x轴坐标,每个K线均匀分布,显示正常。 - 换成timestamp索引后,索引变成了
datetime64类型的时间戳。plt.bar()会把时间戳转成对应的数值(比如从1970年开始的秒数)作为x轴坐标,但你的数据中时间间隔并不均匀(有的间隔40秒,有的55秒),导致K线在x轴上的间距忽大忽小,甚至重叠,自然显示异常。
另外,plt.xticks()处理时间索引时会自动生成刻度,和手动绘制的K线位置不匹配,进一步让图变得混乱。
解决办法
如果要使用timestamp作为索引并正常绘制蜡烛图,可以做以下调整:
- 保留整数位置作为x轴坐标,手动设置x轴刻度为时间戳:
def plotCandles(df): df.set_index('timestamp', inplace=True) plt.figure() up = df[df.close >= df.open] down = df[df.close < df.open] col1 = 'green' col2 = 'red' width = .3 width2 = .03 # 使用整数位置作为x轴坐标 x_pos = range(len(df)) # 为up和down匹配对应的x位置 up_x = [x_pos[i] for i in df.index.get_indexer(up.index)] down_x = [x_pos[i] for i in df.index.get_indexer(down.index)] # 绘制上涨K线 plt.bar(up_x, up.close-up.open, width, bottom=up.open, color=col1) plt.bar(up_x, up.high-up.close, width2, bottom=up.close, color=col1) plt.bar(up_x, up.low-up.open, width2, bottom=up.open, color=col1) # 绘制下跌K线 plt.bar(down_x, down.close-down.open, width, bottom=down.open, color=col2) plt.bar(down_x, down.high-down.open, width2, bottom=down.open, color=col2) plt.bar(down_x, down.low-down.close, width2, bottom=down.close, color=col2) # 设置x轴刻度为时间戳 plt.xticks(x_pos, df.index.strftime('%H:%M:%S'), rotation=30, ha='right') plt.show()
- 或者使用专门的金融绘图库(如
mplfinance),它原生支持时间索引的蜡烛图绘制,无需手动处理坐标:
import mplfinance as mpf def plotCandles(df): df.set_index('timestamp', inplace=True) mpf.plot(df, type='candle', style='yahoo')
内容的提问来源于stack exchange,提问作者Jan
相关产品推荐
相关产品推荐

