我一直在尝试从两个数据框中绘制一个图,其中包含每月时间序列的排放值。第一个是数据框 (df1),其中包含以下列日期、年、月和排放。第二个数据框 (df2) 包含相同的列,但每个月包含不同的流量值。我想使用这两个数据帧在同一个图中绘制一个图。数据框 df1 必须是一个线图,x 轴为日期,y 轴为流量。第二个数据框 (df2) 必须是一个箱形图,x 轴作为日期,y 轴作为每个月的分组流量。
这是我测试过的代码
df1 = pd.DataFrame({
'date': ['2023-04-01', '2023-03-01', '2023-02-01', '2023-01-01', '2022-12-01'],
'year': [2023,2023,2023,2023,2022],
'month': [4,3,2,1,12],
'discharge': [10, 20, 30, 15, 25]
})
# Define the start and end dates
start_date = datetime(2023, 5, 1)
end_date = datetime(2023, 9, 1)
# Generate the date range
dates = pd.date_range(start=start_date, end=end_date, freq='MS')
# Define the values for the DataFrame
df2 = {'date': dates.repeat(10),
'year': [d.year for d in dates] * 10,
'month': [d.month for d in dates] * 10,
'discharge': [i+1 for i in range(len(dates))] * 10}
# Plot
fig, ax = plt.subplots()
ax.plot(df1['date'], df1['discharge'], label='Discharge');
# plot the box plot
df2.boxplot(column='discharge', by='month', positions=[df2['date'][2]], widths=10, ax=ax)
我收到这个错误
ValueError: List of boxplot statistics and
位置 values must have same the length
错误的原因是因为
pos
对于df2['date'][2]
只有一个值。但是,即使您使用 unique() 手动给出其他值,它也不会起作用。有几个问题。一是您需要对折线图和箱形图都使用日期时间。我假设您希望日期逐渐增加,并且两个图的 y 轴需要相同。
为此,您需要首先将每个点(对于两个地块)转换为一个整数,该整数是从两个地块的最早日期算起的天数。然后,将为每个点计算偏移量(从最早日期算起的天数)并绘制在整数轴上。灌封后,您需要将 x-ticks 改回日期格式...下面是代码,我提供了尽可能多的评论。希望这就是您要找的...
import datetime
df1 = pd.DataFrame({'date': ['2023-04-01', '2023-03-01', '2023-02-01', '2023-01-01', '2022-12-01'], 'year': [2023,2023,2023,2023,2022], 'month': [4,3,2,1,12], 'discharge': [10, 20, 30, 15, 25]})
df1['date']=pd.to_datetime(df1['date'])
# Define the start and end dates
start_date = datetime.datetime(2023, 5, 1)
end_date = datetime.datetime(2023, 9, 1)
# Generate the date range
dates = pd.date_range(start=start_date, end=end_date, freq='MS')
# Define the values for the DataFrame
df2 = pd.DataFrame({'date': dates.repeat(10), 'year': [d.year for d in dates] * 10, 'month': [d.month for d in dates] * 10, 'discharge': [i+1 for i in range(len(dates))] * 10})
## Get the earliest date in BOTH plots combined
begin=pd.concat([df1.date, pd.Series(df2.date.unique())]).min()
## Add columns linepos and boxpos to the dataframes to show offset from earliest date
df1['linepos']=(df1['date']-begin).dt.days
df2['boxpos']=(df2['date']-begin).dt.days
## Plot plots - note I am using boxpos and linepos, not dates for x-axis
ax=df2[['discharge', 'boxpos']].boxplot(by='boxpos', widths=4, positions=df2.boxpos.unique(), figsize=(20,7))
ax.plot(df1['linepos'], df1['discharge'], label='Discharge')
## Set x-lim to include both line and boxes
ax.set_xlim( [ min(df2.boxpos.min(), df1.linepos.min())-10, max(df2.boxpos.max(), df1.linepos.max()) + 10 ] )
## To change the x-axis ticks, get the list of all x-entries and sort
locs=(list(df2.boxpos.unique())+list(df1.linepos.unique()))
locs.sort()
ax.set_xticks(locs)
## To add labels get unique dates, sort them, convert to format you like and plot
ax.set_xticklabels(pd.concat([df1.date, pd.Series(df2.date.unique())]).sort_values().reset_index(drop=True).dt.strftime('%Y-%m-%d'), rotation=45 )
## Set x and y labels
ax.set_xlabel('Dates')
ax.set_ylabel('Discharge')