python - 使用 Pandas 在不重叠的全天时间窗口上计算统计功能
问题描述
前言
如何将函数应用于具有非重叠滑动窗口的列表。例如data = {x_1, x_2, ...., x_n}
,我们应用窗口大小为 2 的 f 来获得{f(x_1,x_2), f(x_3, x_4), ...., f(x_{n-1}, x_n)}
.
我知道我可以在分区列表上进行分区和使用 map。但是有没有更有效的方法来处理这个操作,尤其是对于 ndarray 和 dataframe?类似于BlockMap
Mathematica 的东西。
问题
这样做的最终目标是:假设数据框是一个时间序列,其中包含一天中每个小时的值。如何每天应用一个函数(例如平均值、方差),即具有 24 小时大小的非重叠窗口的函数块图?
编辑1:这是一个返回熊猫数据框的代码:
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()
解决方案
(编辑:回答何时没有编辑并标题为:在数据框或 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]
这包括两个步骤:分组分离和映射。可以在 中找到更通用的组flyingcircus.base.group_by()
分离版本。(免责声明:我是该包的主要作者)。
虽然以上适用于一般情况,但如果您有一个 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
关键字(例如np.mean()
,np.std()
等)的 NumPy 函数,可以简单地使用以下重塑技巧:
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])
推荐阅读
- azure - 是否保证序列号将增加 1 EventHub?
- kubernetes - 访问prometheus服务器的入口路由规则
- kotlin-coroutines - 协程:join() 和 cancelAndJoin() 的区别
- posix - 在 POSIX sh 中,字符串替换是未定义的。在尝试做 PASS2="${PASS//[${special_chars}]/}"
- java - 从 int 到 char 的类型转换 Int 到 char
- screen - Snakemake 包装器在没有屏幕但不在屏幕内工作
- sql - 查询几个不连续范围的最后一个
- installation - 安装 Cytoscape 时遇到问题:无法访问 App Store
- java - saml 集成 Ruby(IDP) 和 Java(SP)
- html - 图片路径中的额外元素