【问题标题】:Average over a specific time period特定时间段的平均值
【发布时间】:2016-10-12 00:30:30
【问题描述】:

我在 python 中有一个非常大的表,来自 .h5 文件 表格的开头看起来有点像这样:

table =
                [WIND REL DIRECTION  [deg]]  [WIND SPEED  [kts]]  \
735381.370833                            0             0.000000   
735381.370845                            0             0.000000   
735381.370880                            0             0.000000   
735381.370891                            0             0.000000   
735381.370903                            0             0.000000   
735381.370972                            0             0.000000   
735381.370984                            0             0.000000   
735381.370995                            0             0.000000   
735381.371007                            0             0.000000   
735381.371019                            0             0.000000   
...

索引行是数据的时间戳。我需要每 15 秒计算一次平均 WIND REL SPEED 和 WIND SPEED,并将其转换为一行。我真的需要以一种有效的方式来做这件事,这个 .h5 文件很大。

以下是一些相关代码:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from pylab import *
import matplotlib.dates as pltd
import tables

pltd.num2date(table.index) #to turn the timestamp into a date

我对此一无所知,感谢所有帮助。

【问题讨论】:

  • 冒着成为“我们最了解”类型的人的风险,将平均速度作为新行放入听起来不是一个好主意。这样您的专栏WIND SPEED 包含两种不同类型的信息。我书中的灾难秘诀。
  • 是的,对不起我的英语,我不打算将平均值放在已经存在的风速之间,我打算删除前 15 秒然后放入平均值,或者制作一个带有平均值的新表。
  • 正如 cmets 中对当前 2 个可用答案的讨论:当前答案似乎对风速产生了正确的结果,但两者都对风向产生了不合理的结果,这需要特殊处理,因为它代表圆形数据。 2°和358°的平均风向是360°(或0°),但不是180°,算术平均值是多少。

标签: python pandas


【解决方案1】:

resample 是你的朋友。

idx = pltd.num2date(table.index)
df = pd.DataFrame({'direction': np.random.randn(10), 
                   'speed': np.random.randn(10)}, 
                  index=idx)

>>> df
                                  direction     speed
2014-05-28 08:53:59.971204+00:00   0.205429  0.699439
2014-05-28 08:54:01.008002+00:00   0.383199 -0.392261
2014-05-28 08:54:04.031995+00:00  -2.146569 -0.325526
2014-05-28 08:54:04.982402+00:00   1.572352  1.289276
2014-05-28 08:54:06.019200+00:00   0.880394 -0.440667
2014-05-28 08:54:11.980795+00:00  -1.343758  0.615725
2014-05-28 08:54:13.017603+00:00  -1.713043  0.552017
2014-05-28 08:54:13.968000+00:00  -0.350017  0.728910
2014-05-28 08:54:15.004798+00:00  -0.619273  0.286762
2014-05-28 08:54:16.041596+00:00   0.459747  0.524788

>>> df.resample('15S', how='mean') # how='mean' is the default here
                           direction     speed
2014-05-28 08:53:45+00:00   0.205429  0.699439
2014-05-28 08:54:00+00:00  -0.388206  0.289639
2014-05-28 08:54:15+00:00  -0.079763  0.405775

性能类似于@LondonRob 提供的方法。我使用了一个有 100 万行的 DataFrame 进行测试。

df = pd.DataFrame({'direction': np.random.randn(1e6), 'speed': np.random.randn(1e6)}, index=pd.date_range(start='2015-1-1', periods=1e6, freq='1S'))

>>> %timeit df.resample('15S')
100 loops, best of 3: 15.6 ms per loop

>>> %timeit df.groupby(pd.TimeGrouper(freq='15S')).mean()
100 loops, best of 3: 15.7 ms per loop

【讨论】:

  • 它正在计算 15 秒桶中的平均值。请注意存储桶大小为 1、7 和 2。
  • TimeGrouper 方法和resample 方法产生相同的结果。你的可能是两者中的冷却器,因为它是DataFrame API 的适当内置部分。 (我已经给它们计时了,速度是一样的。)
  • 我在TimeGrouper 方法的“防御”中唯一要说的是它与非时间序列情况相同:groupby 然后mean。这可能是一个加分点。
  • 对这个答案的相同评论:小心点。 winddirection 的算术平均值可能不是您想要的。 (2+358)/2 = 160。这可能不是你所期望的。
  • 结果很真实,不知道我想到了什么。这也只是一个警告,这是风速的正确结果,但同时它对风向产生了无意义的结果。不一定针对您,而是针对 OP。
【解决方案2】:

我认为这是做到这一点的“正确”方式。 (虽然它对我来说似乎有点记录不足。无论如何它都有效!)

您需要在 DataFrame 上执行 groupby 并使用称为 TimeGrouper 的东西。

它是这样工作的:

import pandas as pd
import numpy as np

# Create a dataframe. You can ignore all this bit!
periods = 60 * 60
random_dates = pd.date_range('2015-12-25', periods=periods, freq='s')
random_speeds = np.random.randint(100, size=periods)
random_directions = np.random.random(periods)
df = pd.DataFrame({'date': random_dates, 'wind_speed': random_speeds, 'wind_direction': random_directions})
df = df.set_index('date')

# Here's where the magic happens:
grouped15s = df.groupby(pd.TimeGrouper(freq='15S'))
averages_ws_15s = grouped15s.wind_speed.mean()

或者,如果您坚持在列名中包含空格,那么最后一行将变为:

averages_ws_15s = grouped15s['Wind Speed'].mean()

这会导致以下结果:

date
2015-12-25 00:00:00    45.800000
2015-12-25 00:00:15    48.466667
2015-12-25 00:00:30    38.066667
2015-12-25 00:00:45    54.866667
2015-12-25 00:01:00    34.866667
2015-12-25 00:01:15    37.000000
2015-12-25 00:01:30    47.133333
etc....                etc....

【讨论】:

  • 小心点。 winddirection 的算术平均值可能不是您想要的。 (2+358)/2 = 160。这可能不是你所期望的。
  • @Nras,你有没有想出解决 15 秒平均风向的方法?
  • @squar_o 是的,关键是使用循环统计。您可以对这些角度的正弦、余弦值求和,以获得平均角度的最终正弦/余弦值。然后转换回 0 到 360 度之间的角度。 rads = np.deg2rad(direction), s = np.arctan2(np.sum(np.sin(rads)), np.sum(np.cos(rads))), mean_direction = (np.rad2deg(s) + 360) % 360
猜你喜欢
  • 2022-01-08
  • 2019-06-22
  • 2020-03-02
  • 1970-01-01
  • 2021-08-22
  • 2021-02-08
  • 2023-01-12
  • 2020-07-09
  • 2012-08-16
相关资源
最近更新 更多