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

pandas bar plot combined with line plot shows the time axis beginning at 1970

提问人:Santhosh 提问时间:10/14/2020 最后编辑:Trenton McKinneySanthosh 更新时间:11/18/2023 访问量:4501

问:

我正在尝试绘制股票市场图表

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

不知何故,x 轴显示了 1970 年的时间

以下是图形和代码

enter image description here

代码为:

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并将条形更改为线条。B没有运气

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

Python 熊猫 日期时间 matplotlib

评论


答:

2赞 Santhosh 10/14/2020 #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

我得到的情节是

b

2赞 Trenton McKinney 9/9/2021 #2
  • 我不建议绘制具有如此多条形的柱形图。
  • 此答案解释了为什么 xtick 标签存在问题,以及如何解决该问题。
  • 与熊猫一起绘图。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()

enter image description here


  • 为什么 OP x-tick 标签从 1970 年开始?
  • 条形图位置的索引为 0(带熊猫),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

enter image description here

  • 使用条形图,根据日期时间对位置进行索引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.]

enter image description here

  • sns.barplot(x=df.index, y=df.Volume, ax=ax1)位置为 ,因此条形图和折线图未对齐。xtick[ 0 1 2 ... 1553 1554 1555]
-1赞 Clement Waituika 9/28/2023 #3

首先,您必须指定日期格式,然后在底部指定 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()