Python 熊猫从累积的网络数据中获取最后一小时的平均速度
我有一个pandas数据帧,它以一定的(但不是恒定的)间隔记录多个程序累积的网络流量(字节)。这就像某些程序中的“所有时间下载/上传”数据。数据帧不断更新,一些列被删除,一些列被添加。索引为pandas.DatetimeIndex。 看起来像这样:Python 熊猫从累积的网络数据中获取最后一小时的平均速度,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个pandas数据帧,它以一定的(但不是恒定的)间隔记录多个程序累积的网络流量(字节)。这就像某些程序中的“所有时间下载/上传”数据。数据帧不断更新,一些列被删除,一些列被添加。索引为pandas.DatetimeIndex。 看起来像这样: Program_A Program_B Program_C 2020-10-21 19:30:01.352301 100 200
Program_A Program_B Program_C
2020-10-21 19:30:01.352301 100 200 NaN
2020-10-21 19:45:01.245997 200 250 NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ...
2020-10-22 17:30:01.123456 10000 700 NaN
2020-10-22 17:45:01.158689 30000 700 NaN
2020-10-22 18:00:01.191560 50000 700 NaN
2020-10-22 18:15:01.208001 70000 700 NaN
2020-10-22 18:20:28.401580 100000 700 5000
2020-10-22 18:30:01.281731 110000 700 200000
last_hour_avgspeed(myDataFrame)
-->
Program_A 27.7
Program_B 0.0
Program_C 325.0
......
dtype: float64
每次检索数据帧时,我都要计算过去一小时内每列的平均通信速度(字节/秒)。我想要这样的东西:
Program_A Program_B Program_C
2020-10-21 19:30:01.352301 100 200 NaN
2020-10-21 19:45:01.245997 200 250 NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ...
2020-10-22 17:30:01.123456 10000 700 NaN
2020-10-22 17:45:01.158689 30000 700 NaN
2020-10-22 18:00:01.191560 50000 700 NaN
2020-10-22 18:15:01.208001 70000 700 NaN
2020-10-22 18:20:28.401580 100000 700 5000
2020-10-22 18:30:01.281731 110000 700 200000
last_hour_avgspeed(myDataFrame)
-->
Program_A 27.7
Program_B 0.0
Program_C 325.0
......
dtype: float64
数据中可能有NAN,因为某些列在一小时内添加。因此,一个简单的(最后一行-第一行)/3600将不起作用
我对熊猫不熟悉。我首先编写了一个函数:
def avgspeed(series: pd.Series):
lo = series.first_valid_index()
hi = series.last_valid_index()
s = series[hi] - series[lo]
t = (hi - lo).total_seconds()
return s // t if t > 0 else np.nan
然后将其应用于每一列:
myDataFrame.last('H').apply(avgspeed)
我相信这确实给出了正确的结果:一系列列速度对。然而,我觉得这肯定不是最好的方式。矢量化在哪里?我们能一次就得到结果吗
我尝试过另一种方法:
myDataFrame.last("H").resample("T").bfill().diff().mean().floordiv(60)
首先将数据重新采样为1分钟的样本(不是1秒,因为太慢),然后计算差异的平均值,然后将其除以60秒。。。我认为这比第一种方法更愚蠢。但是性能实际上是第一个的两倍。但是,包含NaN的列的结果与第一个列有所不同。我认为,这可能是因为bfill方法带来了一些问题
那么,正确的计算方法是什么呢?我不太明白,但我认为您需要使用groupby和aggregate df.groupby().agg(列='',aggfunc=平均值)
您可以阅读更多信息:嗯,我想我找到了一个矢量化的解决方案:
def get_avgspeed(df: pd.DataFrame, offset: str) -> pd.Series:
"""Calculate average traffic speed in the final period of time based on offset."""
# truncate the dataframe to the last N time units
df = df.truncate(before=(pd.Timestamp.now()- pd.Timedelta(offset)), copy=False)
# calculate the difference between the last and the first valid index per row
t = df.index[-1] - df.apply(pd.Series.first_valid_index)
# df.bfill() will back fill NaNs, so iloc[0] can give us the first valid value per row
# then calculate the value difference: df.iloc[-1] - df.bfill().iloc[0]
# return the speed: v = s/t
return (df.iloc[-1] - df.bfill().iloc[0]) // t.dt.total_seconds()
avg_speed(myDataFrame, '24H')
-->
Program_A 247.0
Program_B 16.0
Program_C 197620.0
Program_X 252943.0
... ...
dtype: float64
在我的测试中,性能似乎比问题中没有矢量化的版本要好一点:1.77ms vs 2.1ms