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
大多数带有条形图的解决方案只是将标签重新格式化为适当的日期时间,但是这是装饰性的,并且不会对齐线图和条形图之间的位置
这个答案的解决方案 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]
因此条形图和线图未对齐。
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
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()
- 3 回答
- 0 关注
- 132 浏览
添加回答
举报