如何在 Pandas 中覆盖“一天期间”的数据以进行绘图
Posted
技术标签:
【中文标题】如何在 Pandas 中覆盖“一天期间”的数据以进行绘图【英文标题】:How to overlay data over a "day period" in Pandas for plotting 【发布时间】:2017-05-29 07:24:43 【问题描述】:我有一个 DataFrame,其中包含一些 (more-sensical) 数据,格式如下:
In[67] df
Out[67]:
latency
timestamp
2016-09-15 00:00:00.000000 0.042731
2016-09-15 00:16:24.376901 0.930874
2016-09-15 00:33:19.268295 0.425996
2016-09-15 00:51:30.956065 0.570245
2016-09-15 01:09:23.905364 0.044203
...
2017-01-13 13:08:31.707328 0.071137
2017-01-13 13:25:41.154199 0.322872
2017-01-13 13:38:19.732391 0.193918
2017-01-13 13:57:36.687049 0.999191
所以它跨越大约 50 天,并且时间戳不每天都在同一时间。我想为每一天叠加一些图,即在同一个图上检查每一天的时间序列。 50 天可能线太多了,但我想有一种“每日季节性”是我想研究的,这似乎是一个有用的可视化,而不是更严格的东西。
如何将这些数据叠加在代表“单日”时间段的同一图上?
我的想法
我对 Pandas 还不是很熟悉,但我设法将我的数据分组到每天的垃圾箱中
In[67]: df.groupby(pd.TimeGrouper('D'))
Out[68]: <pandas.core.groupby.DataFrameGroupBy object at 0x000000B698CD34E0>
现在我一直在尝试确定我应该如何创建一个新的 DataFrame 结构,以便这些图可以按天叠加。这是我无法弄清楚的基本问题 - 我如何利用 DataFrameGroupBy 对象来覆盖图?一个看起来非常基本的方法是只迭代每个 GroupBy 对象,但我这样做的问题是配置 x 轴,使其仅显示独立于特定日期的“每日时间段”,而不是捕获整个时间戳。
将数据拆分为单独的帧并在同一个图中使用某种日期强制调用它们以使用 in this more general answer 方法对我来说似乎不是很好。
您可以使用类似的方式生成伪数据:
import datetime
start_date = datetime.datetime(2016, 9, 15)
end_date = datetime.datetime.now()
dts = []
cur_date = start_date
while cur_date < end_date:
dts.append((cur_date, np.random.rand()))
cur_date = cur_date + datetime.timedelta(minutes=np.random.uniform(10, 20))
【问题讨论】:
【参考方案1】:您没有提到您打算对按天分组的延迟执行什么操作。假设你取平均值,你可以像这样绘制一个简单的折线图:
df = pd.DataFrame(dts)
df.columns = ['Timestamp', 'Latency']
df.groupby(pd.TimeGrouper(key='Timestamp',freq='D')).mean().plot()
【讨论】:
对不起,如果我不清楚 - 我不希望进行任何聚合。我想要一个从时间 0 到时间 24 小时的 x 轴图,并且我想要同一图上 每一天 的时间序列。我了解如何聚合然后绘制。【参考方案2】:如果您为日期和时间添加单独的列,那么您只需针对每个日期的延迟绘制时间。
df = df.assign(date=df.index.date, time=df.index.time)
for date in df.date.unique():
plt.plot('time', 'latency', data=df[df.date == date])
plt.xlabel('latency')
【讨论】:
【参考方案3】:我最近不得不为我正在分析的数据使用随机时间戳事件绘制一个非常相似的图。
您需要在数据框中添加另一列以查找经过的时间
请先确保您的时间戳数据是一个 python 日期时间对象,然后再做
df['Elapsed_Time'] = df['timestamp'] - df['timestamp'][0]
df['Elapsed_Time'] = df['Elapsed_Time'] / datetime.timedelta(days=1)
现在您应该有一个包含经过时间列的数据框(如下所示。我正在使用我自己的数据集向您展示我的意思)
另外,如果您想要每小时而不是每天绘制一个情节。然后在行中使用小时而不是天
df['Elapsed_Time'] = df['Elapsed_Time'] / datetime.timedelta(hours=1)
下一步:绘图
想法是逐行遍历数据集并聚合一天时间范围内的数据,然后附加到列表中
latency = []
next_day = 1
inds = []
for (i, t) in enumerate(list(df['Elapsed_Time'])):
if t < next_day:
inds.append(i)
else:
latency.append(df.iloc[inds]))
next_day += 1
inds = []
plt.plot(latency, "bo--", label="latencyperday")
这是最终结果(使用我自己的数据集向您展示它的样子)。希望这会有所帮助
【讨论】:
【参考方案4】:考虑数据框df
(主要由 OP 提供的代码生成)
import datetime
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
start_date = datetime.datetime(2016, 9, 15)
end_date = datetime.datetime.now()
dts = []
cur_date = start_date
while cur_date < end_date:
dts.append((cur_date, np.random.rand()))
cur_date = cur_date + datetime.timedelta(minutes=np.random.uniform(10, 20))
df = pd.DataFrame(dts, columns=['Date', 'Value']).set_index('Date')
真正的技巧是将索引拆分为日期和时间组件并取消堆叠。然后插值补缺失值
d1 = df.copy()
d1.index = [d1.index.time, d1.index.date]
d1 = d1.Value.unstack().interpolate()
从这里我们可以d1.plot(legend=0)
ax = d1.plot(legend=0)
ax.figure.autofmt_xdate()
但这不是很有帮助。
你可以尝试这样的事情......希望这会有所帮助
n, m = len(d1.columns) // 7 // 4 + 1, 4
fig, axes = plt.subplots(n, m, figsize=(10, 15), sharex=False)
for i, (w, g) in enumerate(d1.T.groupby(pd.TimeGrouper('W'))):
r, c = i // m, i % m
ax = g.T.plot(ax=axes[r, c], title=w, legend=0)
fig.autofmt_xdate()
如何在数周内完成
创建多索引 包括代表一周的时间段 包括星期几 包括一天中的时间unstack
将每周期间放入列中
仍然不相信轴格式
d2 = df.copy()
idx = df.index
d2.index = [idx.weekday_name, idx.time, idx.to_period('W').rename('Week')]
ax = d2.Value.unstack().interpolate().iloc[:, :2].plot()
ax.figure.autofmt_xdate()
【讨论】:
很抱歉没有尽快回复您@piRSquared,但这个答案经过一些调整非常有帮助,谢谢。 @EricHansen 没问题。很高兴我能帮上忙 我放了一个赏金来奖励你。我知道这不是我最初提出的问题,我也不期待答案,但出于好奇,如果我想在每周而不是每天叠加,会像调整索引一样简单吗?我想我只需要索引时间和星期,但这不起作用,因为我有重复的条目,这是有道理的。我一直在尝试用DatetimeIndex
重新索引状态模型,并且一直在苦苦挣扎。
@EricHansen 这是一个非常好的姿态,谢谢。这不是必需的,但我仍然很感激。我已经更新了我的帖子,知道如何做每周的事情。它是半熟的,但它是一个开始。我建议将此作为一个问题提出,甚至可以调整我的建议以满足您的需求,以便您可以与其他人分享您发现的问题作为您自己的问题的答案。
太好了,谢谢。当然,明天我有时间的时候会这样做。我只想说,在过去几周学习 pandas 的过程中,我从你在网站上的几个答案中学到了东西,所以我真的很感激。以上是关于如何在 Pandas 中覆盖“一天期间”的数据以进行绘图的主要内容,如果未能解决你的问题,请参考以下文章
Python:如何使用 pandas 数据框更新(覆盖)Google BigQuery 表