为了账号安全,请及时绑定邮箱和手机立即绑定

pandas 条形图与线图相结合显示了从 1970 年开始的时间轴

pandas 条形图与线图相结合显示了从 1970 年开始的时间轴

PHP
千巷猫影 2023-11-09 10:42:42
我正在尝试绘制股票市场图表时间序列与收盘价以及时间序列与交易量。x 轴以某种方式显示 1970 年的时间下面是图和代码https://i.stack.imgur.com/THvGM.png 代码是:import pandas as pdimport matplotlib.pyplot as pltimport matplotlib.dates as mdatespd_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 stringdate_fmt = '%d-%m-%y'date_formatter = mdates.DateFormatter(date_fmt)ax1.xaxis.set_major_formatter(date_formatter)# set monthly locatorax1.xaxis.set_major_locator(mdates.MonthLocator(interval=1))# set font and rotation for date tick labelsplt.gcf().autofmt_xdate()plt.show()还独立尝试了这两个图,没有ax=axax=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 并将条更改为行。但没有运气不知何故,第一张图之后的 pandas 数据正在改变年份。
查看完整描述

3 回答

?
慕斯王

TA贡献1864条经验 获得超2个赞

我不建议绘制包含如此多条形图的条形图。

此答案解释了xtick 标签存在问题的原因以及如何解决该问题。

绘图与pandas.DataFrame.plot工作没有问题.set_major_locator

测试于python 3.8.11, pandas 1.3.2,matplotlib 3.4.2

import pandas as pd

import matplotlib.pyplot as plt

import matplotlib.dates as mdates

import yfinance as yf  # conda install -c conda-forge yfinance or pip install yfinance --upgrade --no-cache-dir


# download data

df = yf.download('amzn', 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()


https://i.stack.imgur.com/8MHUi.png

  • 为什么 OP x-tick 标签从 1970 年开始?

  • 条形图位置的索引为 0(使用 pandas),0 对应于 1970

    • 请参阅Pandas 条形图更改日期格式

    • 大多数带有条形图的解决方案只是将标签重新格式化为适当的日期时间,但是这是装饰性的,并且不会对齐线图和条形图之间的位置

    • 这个答案的解决方案 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


https://i.stack.imgur.com/ytQfd.png


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.]


https://i.stack.imgur.com/4MxzW.png


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



查看完整回答
反对 回复 2023-11-09
?
潇潇雨雨

TA贡献1833条经验 获得超4个赞

我找不到 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

我得到的情节是

https://i.stack.imgur.com/lrtEN.png


查看完整回答
反对 回复 2023-11-09
?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

首先,您必须指定日期格式,然后在底部指定 Y 轴以仅显示“%Y”年


# Convert 'Filing date' to a datetime format (assuming it's not already)

df_transposed['Filing date'] = pd.to_datetime(df_transposed['Filing date'], format='%Y-%m-%d')  # Specify the format

.

.

.

# Create a figure with two y-axes

fig, ax1 = plt.subplots(figsize=(16, 6))


# Create a bar chart for Total Revenue against Filing Date on the first y-axis

ax1.bar(df_filtered['Filing date'], df_filtered['Total Revenue'], color='b', align='center', alpha=0.5, width=50)  # Adjust bar width as needed

ax1.set_xlabel('Year')

ax1.set_ylabel('Total Revenue in Billions')

ax1.set_title('Total Revenue Over Years Bar Chart and Line Chart')

ax1.tick_params(axis='x', rotation=45)

# Adjust the transparency (alpha) of the horizontal grid lines to make them more faint

ax1.grid(axis='x', alpha=0.5)


# Create a line chart for Total Revenue against Filing Date on the second y-axis

ax2 = ax1.twinx()

ax2.plot(df_filtered['Filing date'], df_filtered['Total Revenue'], '-', color='r')

ax2.set_ylabel('Total Revenue in Billions (Line Chart)')



# Adjust the y-axis limits to match between both axes

min_y = min(ax1.get_ylim()[0], ax2.get_ylim()[0])

max_y = max(ax1.get_ylim()[1], ax2.get_ylim()[1])

ax1.set_ylim(min_y, max_y)

ax2.set_ylim(min_y, max_y)


# Set the x-axis to display only years

plt.gca().xaxis.set_major_formatter(plt.matplotlib.dates.DateFormatter('%Y'))

# Show the combined chart

plt.tight_layout()

plt.show()


查看完整回答
反对 回复 2023-11-09
  • 3 回答
  • 0 关注
  • 83 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信