【问题标题】:pandas bar plot combined with line plot shows the time axis beginning at 1970熊猫条形图结合折线图显示了从 1970 年开始的时间轴
【发布时间】:2020-10-13 20:28:44
【问题描述】:

我正在尝试绘制股市图表

时间序列与收盘价和时间序列与交易量。

x 轴以某种方式显示了 1970 年的时间

以下是图表和代码

代码是:

import pandas as pd

import matplotlib.pyplot as plt
import matplotlib.dates as mdates


pd_data = pd.DataFrame(data, columns=['id', 'symbol', 'volume', 'high', 'low', 'open', 'datetime','close','datetime_utc','created_at'])

pd_data['DOB'] = pd.to_datetime(pd_data['datetime_utc']).dt.strftime('%Y-%m-%d') 

pd_data.set_index('DOB')

print(pd_data)

print(pd_data.dtypes)

ax=pd_data.plot(x='DOB',y='close',kind = 'line')
ax.set_ylabel("price")

#ax.pd_data['volume'].plot(secondary_y=True,  kind='bar')
ax1=pd_data.plot(y='volume',secondary_y=True, ax=ax,kind='bar')
ax1.set_ylabel('Volumne')


# Choose your xtick format string
date_fmt = '%d-%m-%y'

date_formatter = mdates.DateFormatter(date_fmt)
ax1.xaxis.set_major_formatter(date_formatter)

# set monthly locator
ax1.xaxis.set_major_locator(mdates.MonthLocator(interval=1))

# set font and rotation for date tick labels
plt.gcf().autofmt_xdate()

plt.show()

在没有ax=ax的情况下也独立尝试了两个图

ax=pd_data.plot(x='DOB',y='close',kind = 'line')
ax.set_ylabel("price")

ax1=pd_data.plot(y='volume',secondary_y=True,kind='bar')
ax1.set_ylabel('Volumne')

然后价格图正确显示年份,而体积图显示 1970

如果我交换它们

ax1=pd_data.plot(y='volume',secondary_y=True,kind='bar')
ax1.set_ylabel('Volumne')

ax=pd_data.plot(x='DOB',y='close',kind = 'line')
ax.set_ylabel("price")

现在成交量图正确显示年份,而价格图显示年份为 1970 年

我尝试删除 secondary_y 并将 bar 更改为 line。但是没有运气

不知何故,第一张图表之后的熊猫数据正在改变年份。

【问题讨论】:

    标签: python pandas datetime matplotlib plot


    【解决方案1】:

    我找不到1970的原因,而是使用matplotlib.pyplot来绘图而不是间接使用pandas并且还传递datatime数组而不是pandas

    所以下面的代码起作用了

    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    import pandas as pd
    import datetime as dt
    import numpy as np
    
    pd_data = pd.read_csv("/home/stockdata.csv",sep='\t')
    
    pd_data['DOB'] = pd.to_datetime(pd_data['datetime2']).dt.strftime('%Y-%m-%d')
    
    dates=[dt.datetime.strptime(d,'%Y-%m-%d').date() for d in pd_data['DOB']]
    
    plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m/%d/%Y'))
    plt.gca().xaxis.set_major_locator(mdates.MonthLocator(interval=2))
    plt.bar(dates,pd_data['close'],align='center')
    plt.gca().xaxis.set_minor_locator(plt.MultipleLocator(1))
    plt.gcf().autofmt_xdate()
    plt.show()
    

    我创建了一个日期时间格式的日期数组。如果我使用它制作图表,那么日期将不再显示为 1970

    open    high    low close   volume  datetime    datetime2
    35.12   35.68   34.79   35.58   1432995 1244385200000   2012-6-15 10:30:00
    35.69   36.02   35.37   35.78   1754319 1244371600000   2012-6-16 10:30:00
    35.69   36.23   35.59   36.23   3685845 1245330800000   2012-6-19 10:30:00
    36.11   36.52   36.03   36.32   2635777 1245317200000   2012-6-20 10:30:00
    36.54   36.6    35.8    35.9    2886412 1245303600000   2012-6-21 10:30:00
    36.03   36.95   36.0    36.09   3696278 1245390000000   2012-6-22 10:30:00
    36.5    37.27   36.18   37.11   2732645 1245376400000   2012-6-23 10:30:00
    36.98   37.11   36.686  36.83   1948411 1245335600000   2012-6-26 10:30:00
    36.67   37.06   36.465  37.05   2557172 1245322000000   2012-6-27 10:30:00
    37.06   37.61   36.77   37.52   1780126 1246308400000   2012-6-28 10:30:00
    37.47   37.77   37.28   37.7    1352267 1246394800000   2012-6-29 10:30:00
    37.72   38.1    37.68   37.76   2194619 1246381200000   2012-6-30 10:30:00
    

    我得到的情节是

    【讨论】:

      【解决方案2】:
      • 我不建议绘制包含如此多条形的条形图。
      • 此答案解释了为什么 xtick 标签存在问题,以及如何解决该问题。
      • 使用pandas.DataFrame.plot 绘图可以正常使用.set_major_locator
      • python 3.8.11pandas 1.3.2matplotlib 3.4.2中测试
      import pandas as pd
      import matplotlib.pyplot as plt
      import matplotlib.dates as mdates
      import pandas_datareader as web  # conda install -c anaconda pandas-datareader or pip install pandas-datareader
      
      # download data
      df = web.DataReader('amzn', data_source='yahoo', start='2015-02-21', end='2021-04-27')
      
      # plot
      ax = df.plot(y='Close', color='magenta', ls='-.', figsize=(10, 6), ylabel='Price ($)')
      
      ax1 = df.plot(y='Volume', secondary_y=True, ax=ax, alpha=0.5, rot=0, lw=0.5)
      ax1.set(ylabel='Volume')
      
      # format
      date_fmt = '%d-%m-%y'
      years = mdates.YearLocator()   # every year
      yearsFmt = mdates.DateFormatter(date_fmt)
      
      ax.xaxis.set_major_locator(years)
      ax.xaxis.set_major_formatter(yearsFmt)
      
      plt.setp(ax.get_xticklabels(), ha="center")
      plt.show()
      


      • 为什么 OP x-tick 标签是从 1970 年开始的?
      • 条形图位置的索引为 0(使用 pandas),0 对应于 1970
        • Pandas bar plot changes date format
        • 大多数带有条形图的解决方案只是将标签重新格式化为适当的日期时间,但这只是装饰性的,不会对齐线形图和条形图之间的位置
        • answer解决方案 2 展示了如何更改刻度定位器,但是当可以使用 plt.bar 时,真的不值得额外的代码。
      print(pd.to_datetime(ax1.get_xticks()))
      
      DatetimeIndex([          '1970-01-01 00:00:00',
                     '1970-01-01 00:00:00.000000001',
                     '1970-01-01 00:00:00.000000002',
                     '1970-01-01 00:00:00.000000003',
                     ...
                     '1970-01-01 00:00:00.000001552',
                     '1970-01-01 00:00:00.000001553',
                     '1970-01-01 00:00:00.000001554',
                     '1970-01-01 00:00:00.000001555'],
                    dtype='datetime64[ns]', length=1556, freq=None)
      
      ax = df.plot(y='Close', color='magenta', ls='-.', figsize=(10, 6), ylabel='Price ($)')
      print(ax.get_xticks())
      ax1 = df.plot(y='Volume', secondary_y=True, ax=ax, kind='bar')
      print(ax1.get_xticks())
      ax1.set_xlim(0, 18628.)
      
      date_fmt = '%d-%m-%y'
      years = mdates.YearLocator()   # every year
      yearsFmt = mdates.DateFormatter(date_fmt)
      
      ax.xaxis.set_major_locator(years)
      ax.xaxis.set_major_formatter(yearsFmt)
      
      [out]:
      [16071. 16436. 16801. 17167. 17532. 17897. 18262. 18628.]  ← ax tick locations
      [   0    1    2 ... 1553 1554 1555]  ← ax1 tick locations
      

      • 使用plt.bar,条形图位置根据日期时间编制索引
      ax = df.plot(y='Close', color='magenta', ls='-.', figsize=(10, 6), ylabel='Price ($)', rot=0)
      plt.setp(ax.get_xticklabels(), ha="center")
      print(ax.get_xticks())
      
      ax1 = ax.twinx()
      ax1.bar(df.index, df.Volume)
      print(ax1.get_xticks())
      
      date_fmt = '%d-%m-%y'
      years = mdates.YearLocator()   # every year
      yearsFmt = mdates.DateFormatter(date_fmt)
      
      ax.xaxis.set_major_locator(years)
      ax.xaxis.set_major_formatter(yearsFmt)
      
      [out]:
      [16071. 16436. 16801. 17167. 17532. 17897. 18262. 18628.]
      [16071. 16436. 16801. 17167. 17532. 17897. 18262. 18628.]
      

      • sns.barplot(x=df.index, y=df.Volume, ax=ax1)xtick 位置为 [ 0 1 2 ... 1553 1554 1555],因此条形图和线图未对齐。

      【讨论】:

        猜你喜欢
        • 2022-01-14
        • 1970-01-01
        • 2019-06-25
        • 1970-01-01
        • 2021-03-31
        • 1970-01-01
        • 1970-01-01
        • 2020-11-17
        • 2017-06-05
        相关资源
        最近更新 更多