【问题标题】:Matplotlib plotting multiple line graph into one axesMatplotlib 将多条折线图绘制成一个轴
【发布时间】:2021-11-01 00:09:54
【问题描述】:

我对 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)

我得到的结果是这样的:

我想得到的是这样的:

感谢您的帮助

【问题讨论】:

  • 我怀疑将所有内容转换为str 是您的问题。你为什么这样做?当你把它们变成字符串时,matplotlib 应该如何将它们绘制成时间?
  • 我记得我收到一条错误消息,告诉我不能使用 datetime 对象,我应该使用 str 还是 ...? (不记得了)这就是为什么我将所有转换为 str。

标签: python pandas dataframe datetime matplotlib


【解决方案1】:

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

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()

【讨论】:

  • Zephyr 感谢您的努力。我会试试这个。
猜你喜欢
  • 2017-01-02
  • 2020-05-06
  • 2019-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-09
  • 1970-01-01
  • 2021-04-22
相关资源
最近更新 更多