Python 在数据帧的列中满足条件且无重复计数条纹时跟踪3天条纹

Python 在数据帧的列中满足条件且无重复计数条纹时跟踪3天条纹,python,pandas,numpy,Python,Pandas,Numpy,我有一个由8个不同美国城市的气候观测数据组成的数据框架 我试图找出数据集中每个位置每年的热浪数量(连续3天,最高温度为90度或以上) 我将热浪定义为连续3天,但只有连续3天。例如: If Aug. 8 hit 87 Aug. 9 hit 90 Aug. 10 hit 92 Aug. 11 hit 94 Aug. 12 hit 93 Aug. 13 hit 101 Aug. 14 hit 94 Aug. 15 hit 77 在“热浪”一栏中,8月9日和8

我有一个由8个不同美国城市的气候观测数据组成的数据框架

我试图找出数据集中每个位置每年的热浪数量(连续3天,最高温度为90度或以上)

我将热浪定义为连续3天,但只有连续3天。例如:

If Aug. 8 hit 87
   Aug. 9 hit 90
   Aug. 10 hit 92
   Aug. 11 hit 94
   Aug. 12 hit 93
   Aug. 13 hit 101
   Aug. 14 hit 94
   Aug. 15 hit 77
在“热浪”一栏中,8月9日和8月12日的数值为“1”,反映了两个不同的3天周期,其中最大值达到90或以上

我目前的策略并没有在这样连续的日子里奏效

我一直在尝试使用np.where。首先,我要检查当天的温度是否达到90或以上。接下来,我会提前检查,看看在接下来的两天,最大值是否达到或超过90。最后,我检查了前两天的热浪列是否没有“1”。如果满足所有这些条件,则在行的“热浪”列中放置1

summer['Next90'] = summer.Max.shift(-1)
summer['Following90'] = summer.Max.shift(-2)
summer['HeatWave'] = 0    
summer['HeatWave'] = np.where((summer['Next90']>=90) & 
(summer['Max']>=90) & (summer['Following90']>=90) & (summer.shift(1) 
['HeatWave']!=1) & (summer.shift(2)['HeatWave']!=1), 1, np.nan) 

这个序列的问题是,我不认为np.where可以在“HeatWave”列在前一行中放置1(或np.nan)之后检查它。所以,我在热浪专栏中得到了很多“1”,但是序列最终被重复计算。我还使用iterrows在for循环中尝试了这一点,但也遇到了同样的困难。有人能提出更好的方法吗?

这里是一种你可以尝试的方法(示例数据显示在文章末尾)

  • 获取数据,然后设置条纹天数=3

    df = pd.read_csv('/path/to/file', sep='\s\s+', engine='python', parse_dates=['date'])
    # N-day streak
    N = 3
    
  • 删除潜在的重复,修复丢失的日期,并将NULL“temp”设置为0

    # if there are duplicates in the same date, drop them and keep the one with highest temp
    df = df.sort_values(['date', 'temp'], ascending=[1,0]).drop_duplicates(subset=['date'])
    
    # fix missing dates issue and fill missing 'temp' with 0
    df = df.set_index('date').asfreq('D').reset_index().fillna(0)
    print(df)
    #         date  temp
    #0  2018-08-01    83
    #1  2018-08-02    99
    #2  2018-08-03    99
    #3  2018-08-04    87
    #4  2018-08-05    90
    #5  2018-08-06    92
    #6  2018-08-07     0
    #7  2018-08-08    92
    #8  2018-08-09    90
    #9  2018-08-10    92
    #10 2018-08-11    94
    #11 2018-08-12    93
    #12 2018-08-13   101
    #13 2018-08-14    94
    #14 2018-08-15    77
    
  • 设置符合热浪条件的条件

    # contition-1  df.temp >= 90
    c1 = df.temp.ge(90)
    
  • 根据条件1对连续行进行分组,并用g标记它们

    # group label (each group forms a streak)
    g = (c1 != c1.shift()).cumsum()
    
  • 定义一个新的df1。对于每组g,请查找以下内容:

    • cnt:行的总数
    • n:cumcount()作为序列号
    • g:这里加的只是参考,不用于以后的计算

      df1 = df.assign(
          cnt=df.groupby(g).date.transform('count')
        , n=df.groupby(g).agg('cumcount')
        , g=g
      )
      print(df1)
      #         date  temp  cnt  g  n
      #0  2018-08-01    83    1  1  0
      #1  2018-08-02    99    2  2  0
      #2  2018-08-03    99    2  2  1
      #3  2018-08-04    87    1  3  0
      #4  2018-08-05    90    2  4  0
      #5  2018-08-06    92    2  4  1
      #6  2018-08-07     0    1  5  0
      #7  2018-08-08    92    7  6  0
      #8  2018-08-09    90    7  6  1
      #9  2018-08-10    92    7  6  2
      #10 2018-08-11    94    7  6  3
      #11 2018-08-12    93    7  6  4
      #12 2018-08-13   101    7  6  5
      #13 2018-08-14    94    7  6  6
      #14 2018-08-15    77    1  7  0
      
  • 再定义两个条件:

    # condition-2: cnt >= N , a streak must have at least N rows
    c2 = df1.cnt.ge(N)
    
    # condition-3: (n%N)==0 and (n+N) <= cnt
    # the last n%N==0 might not have enough dates for a N-day streak
    c3 = df1.n.mod(N).eq(0) & df1.n.le(df1.cnt-N)
    
  • 删除临时df1:

    del(df1)
    
  • 样本数据

    date           temp
    Aug 1, 2018    83
    Aug 2, 2018    99
    Aug 2, 2018    65
    Aug 3, 2018    99
    Aug 2, 2018    70
    Aug 4, 2018    87
    Aug 5, 2018    90
    Aug 6, 2018    92
    Aug 8, 2018    92
    Aug 9, 2018    90
    Aug 10, 2018    92
    Aug 11, 2018    94
    Aug 12, 2018    93
    Aug 13, 2018    101
    Aug 14, 2018    94
    Aug 15, 2018    77
    

    您希望从这些数据中得到什么?因此,基本上,我的数据框在连续三天的开始时,热浪列中会有一个“1”,最大值>=90。在至少2天过去之前,热浪列中不会有另一个“1”,不管接下来的2天是否也有一个最大值>=90(防止重复计算连续3天)。这绝对是太棒了(我说这个还没有测试过,但今晚我会这么做)。我非常感谢你花时间发送这个!工作出色!我甚至都说不出我有多么感谢你。下面是一个小代码片段:
    climate[(climate['City']='DFW')&(climate['Year']==2015)和(climate['Max']>=90)]Out[13]:Max-Min-Avg。。。年月日。。。2015-05-18   91.0  68.0  79.5  ...      2015-05南0 2015-06-03 91.0 72.0 81.5。。。2015-06南1
    @wnjl,我很高兴它对你有用。如果我的答案有帮助的话,你介意投我一票吗。享受一个美好的周末:-)我试过了,但还不能算我的得票:-(我想我太新了。
    date           temp
    Aug 1, 2018    83
    Aug 2, 2018    99
    Aug 2, 2018    65
    Aug 3, 2018    99
    Aug 2, 2018    70
    Aug 4, 2018    87
    Aug 5, 2018    90
    Aug 6, 2018    92
    Aug 8, 2018    92
    Aug 9, 2018    90
    Aug 10, 2018    92
    Aug 11, 2018    94
    Aug 12, 2018    93
    Aug 13, 2018    101
    Aug 14, 2018    94
    Aug 15, 2018    77