首页 > 解决方案 > Matplotlib 将多条折线图绘制成一个轴

问题描述

我对 Matplotlib 很陌生,似乎我不明白如何用自定义的 x,y 轴绘制图形。我有一个数据框(请求的 csv 文件),每天有 2 个元素(时间)。我想使用一个 x 轴成对地绘制元素。这是我的代码:

#creating an example dataframe
low = ['08:20','11:50','09:44','11:12']
high = ['10:45','08:05','11:55','09:10']
low = pd.to_datetime(low).time
high = pd.to_datetime(high).time
col_name = ['lowtide','hightide']
ind_val = pd.date_range(start='01-01-2021',periods=4)

df = pd.DataFrame(data= zip(low,high),columns=col_name,index=ind_val)
print(df)

             lowtide  hightide
2021-01-01  08:20:00  10:45:00
2021-01-02  11:50:00  08:05:00
2021-01-03  09:44:00  11:55:00
2021-01-04  11:12:00  09:10:00

在 x 轴上应该有一个时间线,而 y 轴只有低潮和高潮点。我转置了 DataFrame,因为我不知道如何按行绘制并将 column.names 用作 y 轴值并将每个元素设置为 dtype=str,因为 Matplotlib 争论使用 datetime 对象。

#transpose df for plotting because I don't know how to plot row wise
tides = df.T

print(tides)


          2021-01-01  2021-01-02  2021-01-03  2021-01-04
lowtide     08:20:00    11:50:00    09:44:00    11:12:00
hightide    10:45:00    08:05:00    11:55:00    09:10:00

#because of errors while trying to plot I convert all into str
tides = tides.astype(str)

my_xaxis=pd.date_range(start='08:00',end='12:00',freq='5min').time

fig,ax = plt.subplots()
plt.xticks(range(len(my_xaxis)), my_xaxis, rotation='vertical')
plt.yticks(range(len(tides.index)),tides.index)
for column in tides.columns:
    plt.plot(tides[column],tides.index)

我得到的结果是这样的: 在此处输入图像描述

我想得到的是:

在此处输入图像描述

我很感激任何帮助

标签: pythonpandasdataframedatetimematplotlib

解决方案


您应该以这种方式重新塑造您的数据框(也许有一种更简单的重新塑造我不知道的方法):

df = df.reset_index()\
    .melt(id_vars = 'index', var_name = 'tide', value_name = 'time')\
    .set_index('time').pivot(columns = 'index', values = 'tide')\
    .replace({'lowtide': 0, 'hightide': 1})

df.index = df.index.map(lambda x: datetime(year = 2021, month = 1, day = 1, 
                                           hour = x.hour, minute = x.minute, second = x.second))

所以你有了:

index                2021-01-01  2021-01-02  2021-01-03  2021-01-04
time                                                               
2021-01-01 08:05:00         NaN         1.0         NaN         NaN
2021-01-01 08:20:00         0.0         NaN         NaN         NaN
2021-01-01 09:10:00         NaN         NaN         NaN         1.0
2021-01-01 09:44:00         NaN         NaN         0.0         NaN
2021-01-01 10:45:00         1.0         NaN         NaN         NaN
2021-01-01 11:12:00         NaN         NaN         NaN         0.0
2021-01-01 11:50:00         NaN         0.0         NaN         NaN
2021-01-01 11:55:00         NaN         NaN         1.0         NaN

现在您可以绘制:

fig, ax = plt.subplots()

for col in df.columns:
    df[~df[col].isna()][col].plot(label = col.date())

ax.legend(frameon = True)

ax.set_yticks([0, 1])
ax.set_yticklabels(['lowtide', 'hightide'])

ax.xaxis.set_major_locator(md.MinuteLocator(interval = 10))
ax.xaxis.set_major_formatter(md.DateFormatter('%H:%M:%S'))
plt.setp(ax.xaxis.get_majorticklabels(), rotation = 90)

plt.tight_layout()

plt.show()

完整代码

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as md
from datetime import datetime


low = ['08:20','11:50','09:44','11:12']
high = ['10:45','08:05','11:55','09:10']
low = pd.to_datetime(low).time
high = pd.to_datetime(high).time
col_name = ['lowtide','hightide']
ind_val = pd.date_range(start='01-01-2021',periods=4)

df = pd.DataFrame(data= zip(low,high),columns=col_name,index=ind_val)


df = df.reset_index()\
    .melt(id_vars = 'index', var_name = 'tide', value_name = 'time')\
    .set_index('time').pivot(columns = 'index', values = 'tide')\
    .replace({'lowtide': 0, 'hightide': 1})

df.index = df.index.map(lambda x: datetime(year = 2021, month = 1, day = 1,
                                           hour = x.hour, minute = x.minute, second = x.second))


fig, ax = plt.subplots()

for col in df.columns:
    df[~df[col].isna()][col].plot(label = col.date())

ax.legend(frameon = True)

ax.set_yticks([0, 1])
ax.set_yticklabels(['lowtide', 'hightide'])

ax.xaxis.set_major_locator(md.MinuteLocator(interval = 10))
ax.xaxis.set_major_formatter(md.DateFormatter('%H:%M:%S'))
plt.setp(ax.xaxis.get_majorticklabels(), rotation = 90)

plt.tight_layout()

plt.show()

在此处输入图像描述


推荐阅读