将时间绘制在独立轴上。

213

我有一个时间戳数组,格式为(HH:MM:SS.mmmmmm),还有另一个浮点数数组,每个值对应于时间戳数组中的一个值。

我能否使用Matplotlib将时间作为x轴,数字作为y轴进行绘图?

我尝试过,但它似乎只接受浮点数数组。我该如何让它绘制时间?我需要以任何方式修改格式吗?

5个回答

222

更新:

本回答已过时,自 matplotlib 3.5 版本起。现在plot函数可以直接处理日期时间数据。请参见https://matplotlib.org/3.5.1/api/_as_gen/matplotlib.pyplot.plot_date.html

不建议使用 plot_date。该方法存在历史原因,可能会在未来被弃用。

应直接使用 plot 绘制类似日期时间数据的图形。

如果需要将普通数字数据作为 Matplotlib 日期格式绘制或需要设置时区,请在绘图前调用 ax.xaxis.axis_date / ax.yaxis.axis_date。请参阅 Axis.axis_date。


旧、过时的答案:

你必须首先将时间戳转换为Python的datetime对象(使用datetime.strptime)。然后使用date2num将日期转换为matplotlib格式。

使用plot_date绘制日期和数值:

import matplotlib.pyplot as plt
import matplotlib.dates

from datetime import datetime

x_values = [datetime(2021, 11, 18, 12), datetime(2021, 11, 18, 14), datetime(2021, 11, 18, 16)]
y_values = [1.0, 3.0, 2.0]

dates = matplotlib.dates.date2num(x_values)
plt.plot_date(dates, y_values)

enter image description here


6
它会绘制日期还是只有时间?我只需要时间,因为在转换为datetime时,年份将设为1990年。 - randomThought
“...在转换为日期时间时,年份设置为1990”: 您能否提供您用于从字符串转换为日期时间的代码? 转换可能存在问题。 关于图表标签的格式,请参考J.K.Seppänen提供的date_demo1链接。 另外,matplot lib 的文档非常优秀。http://matplotlib.sourceforge.net/index.html - codeape
14
plot_dates --> matplotlib.pyplot.plot_date(dates, values)将日期和数值以散点方式绘制在Matplotlib中的折线图上,可以使用plot_date函数。其中,dates是日期数据,values是对应的数值数据。 - Pete
3
散点图怎么样?我想提供一个大小数组来确定散点气泡的大小,但没有相应的scatter_date()函数,并且没有明显/直接的方法来获取这张图表。 - dwanderson
6
上述代码返回一个类型为matplotlib.lines.Line2D的对象列表。现在我该如何使用它展示图形呢? - Arindam Roychowdhury
@Shayan 我更新了代码示例。 - codeape

107
你也可以使用pyplot.plot将时间戳和值对绘制出来(需要从它们的字符串表示中解析出来)。 (已在matplotlib版本1.2.0和1.3.1中测试过。)
示例:
import datetime
import random
import matplotlib.pyplot as plt

# make up some data
x = [datetime.datetime.now() + datetime.timedelta(hours=i) for i in range(12)]
y = [i+random.gauss(0,1) for i,_ in enumerate(x)]

# plot
plt.plot(x,y)
# beautify the x-labels
plt.gcf().autofmt_xdate()

plt.show()

结果图像:

线性图


这里是相同数据的散点图:

import datetime
import random
import matplotlib.pyplot as plt

# make up some data
x = [datetime.datetime.now() + datetime.timedelta(hours=i) for i in range(12)]
y = [i+random.gauss(0,1) for i,_ in enumerate(x)]

# plot
plt.scatter(x,y)
# beautify the x-labels
plt.gcf().autofmt_xdate()

plt.show()

生成类似于这个的图像:

散点图


4
应该按照我的示例进行操作(将“plot”更改为“scatter”),就可以正常工作。 - moooeeeep
1
我不明白为什么这是我遇到的第五个问题,没有人真正尝试使用散点图 - 它不起作用。类型错误 - 无效的类型提升 - dwanderson
1
@dwanderson,也许你做错了什么。我在我的帖子中添加了一个关于散点图的示例,其中x轴使用了datetime.datetime对象。 - moooeeeep
对于网格,请添加 plt.grid(True) - Christophe Roussy
1
@AimForClarity 在 matplotlib.__version__ 2.2.2 下适用于我。散点图默认设置了一些过宽的 x 轴限制。不过,这个答案提供了一种解决方法,而不是手动调整 plt.xlim(...):https://dev59.com/f3I_5IYBdhLWcg3wAd82#46467896 - moooeeeep
显示剩余4条评论

42

七年后,这段代码仍然帮了我很多。不过,我的时间仍然没有正确显示。

enter image description here

使用Matplotlib 2.0.0,我必须添加以下代码片段,来自Paul H. 的“在 matplotlib 中编辑 x 轴刻度标签的日期格式化”.

import matplotlib.dates as mdates
myFmt = mdates.DateFormatter('%d')
ax.xaxis.set_major_formatter(myFmt)
我将格式更改为(%H:%M),时间正确显示。 enter image description here 感谢社区的帮助。

28

我在使用matplotlib版本2.0.2时遇到了问题。运行以上示例后,我得到了一组居中堆叠的气泡。

graph with centered stack of bubbles

我通过添加另一行来“修复”问题:

plt.plot([],[])

整段代码如下:
import datetime
import random
import matplotlib.pyplot as plt
import matplotlib.dates as mdates


# make up some data
x = [datetime.datetime.now() + datetime.timedelta(minutes=i) for i in range(12)]
y = [i+random.gauss(0,1) for i,_ in enumerate(x)]

# plot
plt.plot([],[])
plt.scatter(x,y)

# beautify the x-labels
plt.gcf().autofmt_xdate()
myFmt = mdates.DateFormatter('%H:%M')
plt.gca().xaxis.set_major_formatter(myFmt)

plt.show()
plt.close()

这会生成一个按要求分布气泡的图像。

graph with bubbles distributed over time


对我来说,在py2.6上无法工作。我得到了ValueError:视图限制最小值-0.05500000000000001小于1,是无效的Matplotlib日期值。如果您将非日期时间值传递给具有日期时间单位的轴,则经常会发生这种情况。 <Figure size 432x288 with 1 Axes> - AimForClarity
解决奇怪的 x-lims 的方法是自行设置它们:https://dev59.com/_2Ei5IYBdhLWcg3wRaqf - Qaswed

6

还没有提到Pandas数据框架。我想展示一下这些如何解决我的日期时间问题。我的日期时间是毫秒级别的2021-04-01 16:05:37。我从/proc中获取linux/haproxy吞吐量,因此我可以按任意格式进行格式化。这非常适合将数据提供给实时图形动画。

这是csv文件的样子。(忽略每秒数据包列,我在另一个图表中使用它)

head -2 ~/data
date,mbps,pps
2021-04-01 16:05:37,113,9342.00
...

通过使用print(dataframe.dtype),我可以看到数据是如何被读取的:
(base) ➜  graphs ./throughput.py
date      object
mbps      int64
pps       float64
dtype:    object

Pandas将日期字符串作为"object"导入,这只是字符类型。如果直接在脚本中使用它:
import matplotlib.pyplot as plt
import pandas as pd

dataframe = pd.read_csv("~/data")

dates = dataframe["date"]
mbps = dataframe["mbps"]

plt.plot(dates, mbps, label="mbps")
plt.title("throughput")
plt.xlabel("time")
plt.ylabel("mbps")
plt.legend()
plt.xticks(rotation=45)

plt.show()

在此输入图片描述

Matplotlib可以呈现所有毫秒级的时间数据。我已经添加了plt.xticks(rotation=45)来倾斜日期,但这并不是我想要的。我可以将日期“对象”转换为datetime64[ns],Matplotlib知道如何呈现它。

dataframe["date"] = pd.to_datetime(dataframe["date"]) 

这次我的日期类型是 datetime64[ns]

(base) ➜  graphs ./throughput.py
date    datetime64[ns]
mbps             int64
pps            float64
dtype:          object

同样的脚本只有一行不同。

#!/usr/bin/env python
import matplotlib.pyplot as plt
import pandas as pd

dataframe = pd.read_csv("~/data")

# convert object to datetime64[ns]
dataframe["date"] = pd.to_datetime(dataframe["date"]) 

dates = dataframe["date"]
mbps = dataframe["mbps"]

plt.plot(dates, mbps, label="mbps")
plt.title("throughput")
plt.xlabel("time")
plt.ylabel("mbps")
plt.legend()
plt.xticks(rotation=45)

plt.show()

这可能不是你使用情况的理想选择,但它可能会对其他人有所帮助。 enter image description here

1
这节省了我很多时间和挫折,感谢分享!有没有想法如何让x轴标签的日期以日-月-年-时-分的格式显示? - Ruben
2
太棒了!是的,创建一个子图来访问x轴属性。这是一条注释,所以很难展示它,但是从我上面的例子中添加fig,ax = plt.subplots(),并在.show()之前添加date_form = DateFormatter("%d-%m-%Y-%H-%M")ax.xaxis.set_major_formatter(date_form) - b0bu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接