【问题标题】:Compute stats function on non-overlapping day-wide time window with Pandas使用 Pandas 在不重叠的全天时间窗口上计算统计功能
【发布时间】:2019-07-16 16:02:01
【问题描述】:

序言

如何将函数应用于具有非重叠滑动窗口的列表。例如。 data = {x_1, x_2, ...., x_n} 并且我们应用 f 和窗口大小 2 来获得 {f(x_1,x_2), f(x_3, x_4), ...., f(x_{n-1}, x_n)}

我了解我可以在分区列表上进行分区和使用 map。但是有没有更有效的方法来处理这个操作,尤其是对于 ndarray 和 dataframe?类似于 Mathematica 的 BlockMap 的东西。

问题

这样做的最终目标是:假设数据框是一个时间序列,其中包含一天中每个小时的值。如何每天应用一个函数(例如平均值、方差),即具有 24 小时大小的非重叠窗口的函数块图?

编辑 1: 这是一个返回 pandas 数据框的代码:

import pandas as pd
import numpy as np

dat = np.random.uniform(0,10,40)
xpd = pd.DataFrame(dat)

xpd.rename(columns = {0:'new_name'}, inplace = True)
date_rng = pd.date_range(start='1/1/2018 03:00:00', periods=40, freq='H') 
xpd.set_index(date_rng, inplace=True)

我如何计算每天的方差,即从每小时数据,并作为数据框返回。 我尝试了以下行,但没有成功:

xpd.groupby(by=lambda x: pd.Series.dt.floor(x, freq='d'))

编辑 2 这行得通,问题似乎解决了:

xpd.groupby(by=lambda x: x.floor('d')).var()

【问题讨论】:

  • n % 2 != 0的情况你想怎么处理?
  • @norok2 假设它是偶数,或者只是左右填充相同的值。
  • 这不是另一个变体,这是一个完全不同的问题,除非你有一个恒定的时间步长并且你可以依赖行数。你可能应该问一个新问题。
  • @norok2 是的,时间步长确实是恒定的。
  • 是的,定义不明确。

标签: python pandas numpy dataframe time-series


【解决方案1】:

(编辑:在没有编辑时回答,标题为:在数据框或 ndarray 上映射具有非重叠窗口的函数)。


假设n 总是偶数,一种方法是:

def pairwise_map(func, items):
    iterators = [iter(items)] * 2
    return map(func, zip(*iterators))


list(pairwise_map(sum, range(10)))
# [1, 5, 9, 13, 17]

这包括两个步骤:group 中的分离和映射。 可以在flyingcircus.base.group_by() 中找到更通用的 group 分隔版本。 (免责声明:我是包的主要作者)。


虽然上述方法适用于一般情况,但如果您有一个 NumPy 数组 arr 并且函数 func() 是矢量化的,则可以简单地使用:

import numpy as np

arr = np.arange(10)


def func(x, y):
    return x + y


func(arr[::2], arr[1::2])
# array([ 1,  5,  9, 13, 17])

编辑

这可以推广到任何大小,例如:

def pairwise_map(func, items, window=2):
    iterators = [iter(items)] * window
    return map(func, zip(*iterators))


list(pairwise_map(sum, range(10), 3))
# [3, 12, 21]

这显然依赖于func() 能够接受正确或可变数量的参数。


同样,对于 NumPy 数组和 NumPy 感知函数:

import numpy as np

arr = np.arange(9)


def func(*args):
    return sum(args)

window = 3
func(*(arr[i::window] for i in range(window)))
# array([ 3, 12, 21])

请注意,这需要len(arr) % window == 0


对于支持 axis 关键字的 NumPy 函数(例如 np.mean()np.std() 等),可以简单地使用以下重塑技巧:

import numpy as np

arr = np.arange(56)
window = 8
np.mean(arr.reshape(-1, window), axis=1)
# array([ 3.5, 11.5, 19.5, 27.5, 35.5, 43.5, 51.5])

请注意,这也严格要求 len(arr) % window == 0,可以通过例如np.concatenate() 在输入末尾补零:

import numpy as np

arr = np.arange(53)
remainder = len(arr) % window
padder = np.zeros(window - remainder if remainder else 0, dtype=arr.dtype)
window = 8
np.mean(np.concatenate((arr, padder)).reshape(-1, window), axis=1)
# array([ 3.5 , 11.5 , 19.5 , 27.5 , 35.5 , 43.5 , 31.25])

【讨论】:

  • 我在上述问题的基础上又添加了一个推论问题。
  • @AlGuy 这是一个完全不同的问题,不是澄清。
  • 但是当窗口很大时,这种方法不会产生问题吗?
  • @AlGuy 不是特别的,但是 NumPy 数组和 NumPy 函数支持 axis 关键字,你最好用不同的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-11
  • 1970-01-01
  • 2021-07-24
  • 1970-01-01
  • 1970-01-01
  • 2013-01-15
相关资源
最近更新 更多