【问题标题】:Using pandas to select specific seasons from a dataframe whose values are over a defined threshold使用 pandas 从值超过定义阈值的数据框中选择特定季节
【发布时间】:2016-03-11 18:24:33
【问题描述】:

为代码墙道歉,但我不能进一步缩短它......

我想以一种确定性的方式根据极端季节(温度大于或小于两个标准差的季节)对气候数据进行采样,也就是说,我可以选择一个温暖的季节,然后是一个寒冷的季节,或者多个温暖的季节,然后是多次感冒等

下面的示例代码应该能说明问题

导入必要的包

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
%matplotlib inline

在列中生成具有随机值的数据框

dates = pd.date_range('20070101',periods=18250)
df = pd.DataFrame(np.random.randn(18250), columns = list ('A'))
df['date'] = dates
df = df[['date','A']]

定义季节函数并按季节拆分数据

def get_season(row):
    if row['date'].month >= 3 and row['date'].month <= 5:
        return '1'
    elif row['date'].month >= 6 and row['date'].month <= 8:
        return '2'
    elif row['date'].month >= 9 and row['date'].month <= 11:
        return '3'
    else:
        return '4'

df['Season'] = df.apply(get_season, axis=1)

如果月份是 12 月,则年份值加 1,因此 12 月 1 月 2 月都在同一年

df['Year'] = df['date'].dt.year
df.loc[df['date'].dt.month == 12, 'Year'] += 1

计算季节平均值

seasmean = df['A'].groupby(df['Season']).mean()

按季节和年份对新数据帧进行多索引

df2 = df.set_index(['Year', 'Season'], inplace=False)
df2.head()
df2.to_csv('df2.csv', sep = ',')

计算季节和季节均值之间的差异

seasdif = df2['A'].groupby(level=['Year','Season']).mean() - seasmean
seasdif

根据标准差可视化季节性差异和极值

seasdif.plot()
plt.axhline(0,color='red')
plt.axhline(seasdif.std() * 2, color ='red')
plt.axhline(-(seasdif.std()) * 2, color ='red')

从中可以清楚地看出,某些季节高于和低于 2 SD 阈值,我希望能够基于此创建一个新的确定性序列,例如,我可以选择一个正常的春天,然后是炎热的夏天,然后是一个炎热的秋天,一个寒冷的冬天(或任何可能的排列)。

编辑

此函数查找暖季和冷季,如果不是极端,则附加 0,如果极端,则分别附加到暖和冷列

seasdif2 = pd.DataFrame(seasdif)
warm = []
cold = []

def extremeseas(seasdif):
    for season in seasdif:
        if season > seasdif.std() * 2:
            warm.append(1)
        else:
            warm.append(0)

    for season in seasdif:
        if season < (-(seasdif.std()*2)):
            cold.append(1)
        else:
            cold.append(0)

将函数应用于数据集:

extremeseas(seasdif)

将列添加到新的数据框以识别极端情况

seasdif2['cold']=cold
seasdif2['warm']=warm
seasdif2

我想根据这些数据生成一个新的气候序列,我可以在其中指定我想要什么样的气候,即我希望能够连续选择 8 个随机季节,然后选择一个随机的春天,然后一个炎热的夏天,接着是一个随机的秋天,接着是一个寒冷的冬天。

我需要能够选择我想要的任何序列,到目前为止,我所做的只是使用以下代码选择 x 年(在本例中为 50 年)的随机序列:

future = pd.DataFrame()

for i in range(50):
    for season in ['1', '2', '3', '4']:
        future = future.append(df2.loc[np.random.choice(range(2007,2050))]
                                  .loc[season])

问题是这选择了一个完全随机的序列,这很好,因为我想要一个随机序列,但我也希望能够在这个序列中插入极端季节/年份,例如20 个随机年份和 3 个极端年份或 10 个随机年份,然后是 3 个寒冷冬天等年份,但不知道如何做到这一点。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    这是一个选择正常春季和温暖夏季的示例(在此示例中仅使用 1 个标准差,而不是 2 个)。

    >>> seasdif[ (abs(seasdif) < seasdif.std()) &                     # within 1 std dev
                 (seasdif.index.get_level_values('Season') == '1') &  # spring 
                 (seasdif.shift(-1) > seasdif.std()) ]                # following summer
    
    Year  Season
    2036  1         0.064691
    2038  1        -0.016453
    2047  1         0.020691
    2053  1         0.063338
    2055  1        -0.045606
    Name: A, dtype: float64
    

    我的随机数据与你的不同,所以这里是我对 2036 的值和下面的标准开发,以便你可以验证代码在做什么。

    >>> seasdif.loc[2036]
    
    Season
    1    0.064691
    2    0.165824
    3   -0.043372
    4    0.086788
    Name: A, dtype: float64
    
    >>> seasdif.std()
    
    0.09357005962032763
    

    【讨论】:

      【解决方案2】:

      以下代码创建了一个数据框,其中包含您的年份、季节、温度、本季异常炎热和寒冷天气的两个标志列,以及上一季异常炎热和寒冷天气的两个标志列。

      首先,复制您的数据框,并将异常天气标志添加到新数据框:

      seasdif2 = pd.DataFrame(seasdif)
      warm = []
      cold = []
      for season in seasdif:
          if season > seasdif.std() * 2:
              warm.append(1)
          else:
              warm.append(0)
      
      for season in seasdif:
          if season < (-(seasdif.std()*2)):
              cold.append(1)
          else:
              cold.append(0)
      
      seasdif2['cold']=cold
      seasdif2['warm']=warm
      

      然后,删除您的温度列“A”,这样您就有一个“仅标志”数据框:

      seasdif2 = seasdif2.drop('A',1)
      

      现在,将您的标志连接到您的原始温度数据帧。通过在连接时移动标志的索引,您可以标记异常天气是否发生在上一季而不是本季。

      在这种情况下,seasdif2 为本季异常温暖和寒冷的天气添加标志列,而 seasdif2.shift(-1) 为上一季异常温暖和寒冷的天气添加列:

      flagged_seasons = pd.concat([seasdif, seasdif2, seasdif2.shift(-1), seasdif2.shift(1)], axis=1)
      

      但是,这样做时要小心,因为您最终会得到多个“暖”和“冷”标志列。确保将由 shift(-1) 添加的列分别重命名为“cold_previous”和“warm_previous”。

      现在您可以选择连续两个季节出现异常天气的行。例如,如果您想查找热季之后是否是冷季,您只需选择warm==1 和cold_previous==1 的数据框行。

      【讨论】:

      • 谢谢这真的有帮助 - 很抱歉没有更清楚,但我不想确定可能极端的连续季节,我只想确定极端(我可以做到感谢您的帮助),然后创建一个包含这些极端情况的新气候序列(例如,10 个“正常”气候年,然后是冬季极度寒冷潮湿的一年,然后是炎热的夏季等),所以我需要制定一个选择极端季节内的所有数据并将其放入具有“正常”观察序列的数据框中的方法......再次感谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-26
      • 2018-03-22
      • 2021-08-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多