0

我看了看 Panda,它可能并不容易用于我的目的。可能有一个 python 工具包,我不知道。你能告诉我什么包可以轻松处理如下所述的情况吗?

我有一系列 2D numpy 气象变量的即时值数组(对于一个地理区域),在特定日期的 0、6、12、...、96、... 小时采样。

我将它作为 python 字典:

values[0]:[[3, 2,...,9, 5][6, 7, ..., 6, 7]]
...
...
values[96]:[[2, 2,...,8, 5][6, 7, ..., 5, 6]]

我需要对可配置的聚合步骤进行平均。例如,对于 24 小时的聚合步骤,我将获得 4 个每日平均值:

values_avg24h=average(values, aggr_step=24)
values_avg24h[24]=[[...][...]]
values_avg24h[48]=[[...][...]]
values_avg24h[72]=[[...][...]]
values_avg24h[96]=[[...][...]]

时间分辨率可以改变。此外,原始值也可以在不同的聚合步骤上进行平均。一个特定的现有软件包可以解决所有这些问题。无论如何,即使是这个简单问题的聪明解决方案也会受到赞赏。

4

2 回答 2

2
import numpy as np

def average(values, aggr_step=24):
    keys = np.array(values.keys())
    bins = range(aggr_step,1+keys.max(),aggr_step)
    npd = np.digitize(keys,bins)
    return {b:np.mean(np.r_[[values[k] for k in keys[npd==i]]],axis=0)
            for i,b in enumerate(bins)}

抽出一些样本值,并测试:

values = {h:np.array([np.random.random_integers(1,10,5) for _ in 'x'*2])
          for h in np.r_[0:100:6]}

{0: array([[ 1,  2, 10,  8,  7],
       [10,  1,  8,  2,  5]]),
 6: array([[ 7, 10,  7,  6,  4],
       [ 9,  4,  6,  1,  1]]),
 12: array([[ 7, 10, 10,  5,  4],
       [ 7,  6,  2,  6,  7]]),
 18: array([[9, 9, 8, 5, 8],
       [8, 9, 6, 1, 2]]),
 24: array([[8, 1, 5, 9, 7],
       [1, 1, 6, 8, 3]]),
 30: array([[ 7,  2,  8,  3,  4],
       [ 5, 10,  5,  6,  5]]),
 36: array([[ 6,  5,  9,  4,  5],
       [ 6, 10,  8, 10, 10]]),
 42: array([[ 2,  2,  6,  6,  9],
       [ 5,  7,  4,  8, 10]]),
 48: array([[10,  1,  1,  1,  8],
       [ 5,  6,  4,  5,  8]]),
 54: array([[ 6,  2,  6,  6,  6],
       [10,  6,  9,  4,  8]]),
 60: array([[ 6,  8,  2,  1,  7],
       [ 1, 10, 10,  2,  3]]),
 66: array([[4, 8, 7, 1, 3],
       [1, 3, 8, 4, 2]]),
 72: array([[ 8,  9,  8,  6,  7],
       [ 1,  4,  2, 10,  1]]),
 78: array([[ 2,  1,  3,  8,  9],
       [ 2,  8,  6, 10,  3]]),
 84: array([[ 1,  8,  9,  4,  3],
       [ 9, 10,  8,  3,  4]]),
 90: array([[ 4,  4,  2,  8,  6],
       [ 1,  3, 10,  2,  6]]),
 96: array([[ 9,  9,  8,  4,  4],
       [ 2,  8, 10,  3,  5]])}

average(values,24)

{24: array([[ 6.  ,  7.75,  8.75,  6.  ,  5.75],
       [ 8.5 ,  5.  ,  5.5 ,  2.5 ,  3.75]]),
 48: array([[ 5.75,  2.5 ,  7.  ,  5.5 ,  6.25],
       [ 4.25,  7.  ,  5.75,  8.  ,  7.  ]]),
 72: array([[ 6.5 ,  4.75,  4.  ,  2.25,  6.  ],
       [ 4.25,  6.25,  7.75,  3.75,  5.25]]),
 96: array([[ 3.75,  5.5 ,  5.5 ,  6.5 ,  6.25],
       [ 3.25,  6.25,  6.5 ,  6.25,  3.5 ]])}
于 2013-04-14T22:00:33.180 回答
2

如果数据是定期采样的(您的帖子似乎表明了这一点),那么pandas肯定可以帮助您。

一种可能的pandas解决方案是创建一个Panel对象,其中items(字典中的类似键)属于 class pandas.tseries.index.DatetimeIndex。然后major_axis, 和minor_axis元素Panel将成为 numpy 数组中的行和列。这听起来有点奇怪,所以我将举一个简单的例子。

>>> import pandas as pd
>>> import numpy as np
>>> start_date = '4/14/2013'  # Start today (default time is midnight)

# create the date_range we will use as panel items
>>> ind = pd.date_range(start=start_date, periods=20, freq='6H')

# Create data: thanks @mtadd
>>> values = {h:np.array([np.random.random_integers(1,10,5) for _ in 'x'*2])
              for h in np.r_[0:120:6]}

# Create the Panel object directly from the dict of 2D np.arrays
>>> my_panel = pd.Panel(values)

# Set the Panel's items to be the date_range we made earlier
>>> my_panel.items = ind

>>> my_panel.ix[0]  # Show first 2D array of data
        0   1   2   3  4
     0  4   3  10   6  6
     1  4  10   7  10  6
>>> values[0]  # Same as above, but from the dict
    array([[ 4,  3, 10,  6,  6],
           [ 4, 10,  7, 10,  6]])

现在我们已经设置好了,我们将使用Panel方法resample。我们将提供两个参数,第一个是我们希望数据处于的新频率,第二个是how我们将指定为的关键字参数mean这是我回答的主要部分!

>>> averaged = my_panel.resample('24H', how='mean')
>>> list(averaged.items)  # Show new time stamps for data
    [<Timestamp: 2013-04-14 00:00:00>,
     <Timestamp: 2013-04-15 00:00:00>,
     <Timestamp: 2013-04-16 00:00:00>,
     <Timestamp: 2013-04-17 00:00:00>,
     <Timestamp: 2013-04-18 00:00:00>]

请注意,'24H'我们为resample方法提供的参数只是 OA 发布的示例的扩展。有关此参数可以采用哪些类型的描述的更多信息,请参阅此链接

为了验证平均值是否正确计算,我们将比较中的第一项与averaged Panel我们手动计算的平均值。

>>> averaged.ix[0]
         0     1     2     3     4
    0  6.5  5.25  7.25  6.25  6.50
    1  5.0  6.75  5.25  6.50  5.25

>>> (values[0] + values[6] + values[12] + values[18]) / 4.
    array([[ 6.5 ,  5.25,  7.25,  6.25,  6.5 ],
           [ 5.  ,  6.75,  5.25,  6.5 ,  5.25]])

items如果您传入一个对象,您可以在时间戳方面拥有更大的灵活性datetime.datetime。例如,如果您在元旦下午 1:37 开始采样并继续采样 50 个时段,您可以这样做:

>>> from datetime import datetime
>>> start = datetime(2013, 1, 1, 13, 37)  # 1:37 on 1/1/2013
>>> ind = pd.date_range(start, periods=50, freq='6H')

然后你会像以前一样继续。您还可以将开始和结束项目传递给 date_range 而不是您希望它生成的周期数。如果我们从与上述相同的开始时间到 2 月 28 日凌晨 4:50,每 2 1/2 小时收集一次数据,您可以执行以下操作:

>>> end = datetime(2013, 2, 28, 4, 50)  # 4:50 AM on 2/28/2013
>>> ind = pd.date_range(start, freq='2H 30MIN')

请注意,您不必传递与您传入的频率完全一致的开始和结束时间。有关如何使用Panel对象或时间序列数据的更多详细信息,pandas请查看这些词中给出的链接。

于 2013-04-15T07:41:35.907 回答