【问题标题】:Compute daily climatology using pandas python使用 pandas python 计算每日气候学
【发布时间】:2014-01-25 05:56:36
【问题描述】:

我正在尝试使用 pandas 来计算每日气候学。我的代码是:

import pandas as pd

dates      = pd.date_range('1950-01-01', '1953-12-31', freq='D')
rand_data  = [int(1000*random.random()) for i in xrange(len(dates))]
cum_data   = pd.Series(rand_data, index=dates)
cum_data.to_csv('test.csv', sep="\t")

cum_data 是包含从 1950 年 1 月 1 日到 1953 年 12 月 31 日的每日日期的数据框。我想创建一个长度为 365 的新向量,第一个元素包含 1950 年、1951 年、1952 年和 1953 年 1 月 1 日的 rand_data 平均值.等等第二个元素...

有什么建议我可以使用 pandas 做到这一点吗?

【问题讨论】:

    标签: python pandas time-series


    【解决方案1】:

    您可以按一年中的某天分组,然后计算这些组的平均值:

    cum_data.groupby(cum_data.index.dayofyear).mean()
    

    但是,您必须注意闰年。这将导致这种方法出现问题。作为替代方案,您还可以按月和日分组:

    In [13]: cum_data.groupby([cum_data.index.month, cum_data.index.day]).mean()
    Out[13]:
    1  1     462.25
       2     631.00
       3     615.50
       4     496.00
    ...
    12  28    378.25
        29    427.75
        30    528.50
        31    678.50
    Length: 366, dtype: float64
    

    【讨论】:

    • 嗨 Joris,您是否知道通过包括相邻天数来计算每日气候学的任何巧妙方法?例如,对于 1 月 3 日和 5 天的窗口,我们的想法是使用所有可用年份的所有 1、2、3、4、5 天并计算平均值。这同样适用于一年中的所有其他日子。 Atm,我可以通过循环来做到这一点,但是如果有任何更聪明和/或更快的方法可以避免循环,那么知道会很有用。
    • 我认为最简单的方法是首先使用 5 天的窗口进行滚动窗口平均值,然后在第二步中按年进行分组(或相反,实际上可能更多像你用更少的数据做滚动窗口一样高效)。如果您有一个固定的时间序列(所有年份的所有日期都可用),那么分两步取平均值应该无关紧要。但如果这不能回答问题,最好打开一个单独的问题。
    【解决方案2】:

    希望它能有所帮助,我想发布我的解决方案,以获得与原始时间序列具有相同索引和长度的气候学系列。

    我使用 joris 的解决方案来获得 365/366 个元素的“气候模型”,然后我从这个模型气候学中获取值,并从我的原始时间序列中获取时间索引来构建我想要的系列。 这样,闰年之类的事情就会自动得到处理。

    #I start with my time series named 'serData'.
    #I apply joris' solution to it, getting a 'model climatology' of length 365 or 366.
    serClimModel = serData.groupby([serData.index.month, serData.index.day]).mean()
    
    #Now I build the climatology series, taking values from serClimModel depending on the index of serData.
    serClimatology = serClimModel[zip(serData.index.month, serData.index.day)]
    
    #Now serClimatology has a time index like this: [1,1] ... [12,31].
    #So, as a final step, I take as time index the one of serData.
    serClimatology.index = serData.index
    

    【讨论】:

      【解决方案3】:

      @乔里斯。谢谢。您的答案正是我需要使用 pandas 来计算每日气候学,但您没有完成最后一步。将所有年份的月、日索引重新映射回一年中的一天索引,包括闰年,即 1 到 366。所以我想我会为其他用户分享我的解决方案。 1950 年到 1953 年是 4 年,其中有一个闰年,即 1952 年。请注意,由于使用的是随机值,因此每次运行都会给出不同的结果。

      ...   
      from datetime import date
      doy = []
      doy_mean = []
      doy_size = []
      for name, group in cum_data.groupby([cum_data.index.month, cum_data.index.day]):
        (mo, dy) = name
        # Note: can use any leap year here.
        yrday = (date(1952, mo, dy)).timetuple().tm_yday
        doy.append(yrday)
        doy_mean.append(group.mean())
        doy_size.append(group.count())
        # Note: useful climatology stats are also available via group.describe() returned as dict
        #desc = group.describe()
        # desc["mean"], desc["min"], desc["max"], std,quartiles, etc.
      
      # we lose the counts here.
      new_cum_data  = pd.Series(doy_mean, index=doy)
      print new_cum_data.ix[366]
      >> 634.5
      
      pd_dict = {}
      pd_dict["mean"] = doy_mean
      pd_dict["size"] = doy_size
      cum_data_df = pd.DataFrame(data=pd_dict, index=doy)
      
      print cum_data_df.ix[366]
      >> mean    634.5
      >> size      4.0
      >> Name: 366, dtype: float64
      # and just to check Feb 29
      print cum_data_df.ix[60]
      >> mean    343
      >> size      1
      >> Name: 60, dtype: float64
      

      【讨论】:

      • 您好@user308827 我正在使用您的新代码来计算每日气候学。但如果我想要armonic手段?我正在使用 doy_harmonic_mean.append(group.statistics.harmonic_mean()) 但我收到错误 AttributeError: 'Series' object has no attribute 'statistics'。我如何在这段代码中应用 armonic 方法?
      猜你喜欢
      • 1970-01-01
      • 2017-07-31
      • 2019-05-20
      • 2019-07-16
      • 1970-01-01
      • 2013-11-28
      • 2019-03-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多