创建一个新变量,该变量是python

时间:2018-12-12 12:57:17

标签: python pandas time-series resampling

当列 A 的值在一周内最高时,如何为变量 S 分配值1?另外,当 B 的值在一周内达到最小值时,如何将值2分配给变量 S 。我正在使用按日期时间索引的每小时数据。 这是我的数据框的样子:

                 A       B      S
datetime            
6/14/2004 1:00  384.5   383.6   0
6/14/2004 2:00  384.3   382.3   0
6/14/2004 3:00  383.3   382.3   0
6/14/2004 4:00  383.3   382.6   0
6/14/2004 5:00  383.3   382.8   0
6/14/2004 6:00  383.3   382.5   0
6/14/2004 7:00  383.3   382.3   0
6/14/2004 8:00  383.8   382.3   0
6/14/2004 9:00  382.8   382.1   0
6/14/2004 10:00 382.6   382.1   0

我尝试使用每周重新采样并获取最大值,但是由于它比我最初想象的要复杂,所以我不怎么编码。 这是我希望最终数据看起来像的样子。

                  A      B      S
datetime            
6/14/2004 1:00  384.5   383.6   0
6/14/2004 2:00  384.3   382.3   0
6/14/2004 3:00  383.3   382.3   0
6/14/2004 4:00  383.3   382.6   0
6/14/2004 5:00  383.3   382.8   0
6/14/2004 6:00  383.3   382.5   0
6/14/2004 7:00  383.3   382.3   0
6/14/2004 8:00  383.8   382.3   0
6/14/2004 9:00  382.8   382.1   0
6/14/2004 10:00 382.6   382.1   0
6/14/2004 11:00 382.5   381.8   0
6/14/2004 12:00 382.8   382.3   0
6/14/2004 13:00 383.1   382.3   0
6/14/2004 14:00 385.8   382.5   0
6/14/2004 15:00 385.1   383.6   0
6/14/2004 16:00 384.8   383.5   0
6/14/2004 17:00 384.8   382.5   0
6/14/2004 18:00 383.6   382.8   0
6/14/2004 19:00 383.8   382.8   0
6/14/2004 20:00 383.3   382.8   0
6/14/2004 21:00 383.1   382.6   0
6/14/2004 22:00 383.1   382.6   0
6/14/2004 23:00 383.1   382.6   0
6/15/2004 0:00  382.8   382.6   0
6/15/2004 1:00  383.3   382.6   0
6/15/2004 2:00  383.6   382.3   0
6/15/2004 3:00  383.8   382.5   0
6/15/2004 4:00  382.8   382.1   0
6/15/2004 5:00  383.0   382.1   0
6/15/2004 6:00  382.8   382.0   0
... ... ... ...
6/24/2004 20:00 402.8   401.8   0
6/24/2004 21:00 402.3   401.8   0
6/24/2004 22:00 402.3   401.8   0
6/24/2004 23:00 402.1   401.1   0
6/25/2004 0:00  402.1   401.8   0
6/25/2004 1:00  402.1   401.3   0
6/25/2004 2:00  402.1   400.1   0
6/25/2004 3:00  401.6   400.8   0
6/25/2004 4:00  401.5   400.8   0
6/25/2004 5:00  401.3   400.8   0
6/25/2004 6:00  401.1   400.6   0
6/25/2004 7:00  402.1   400.8   0
6/25/2004 8:00  402.1   400.6   0
6/25/2004 9:00  401.6   400.5   0
6/25/2004 10:00 401.8   400.8   0
6/25/2004 11:00 401.5   400.6   0
6/25/2004 12:00 401.3   400.1   0
6/25/2004 13:00 402.8   401.3   0
6/25/2004 14:00 402.8   401.0   **1**
6/25/2004 15:00 401.5   400.1   0
6/25/2004 16:00 401.6   400.6   0
6/25/2004 17:00 401.8   401.0   0
6/25/2004 18:00 402.1   400.8   0
6/25/2004 19:00 402.3   400.8   0
6/25/2004 20:00 402.6   401.6   0
6/25/2004 21:00 401.8   401.3   0
6/25/2004 22:00 401.8   400.6   0
6/28/2004 0:00  401.8   401.6   0
6/28/2004 1:00  402.3   401.6   0
6/28/2004 2:00  402.3   401.5   0

对于第一周,列S在 2004/6/18 18:00 中具有值1,在 2004/6/15 11:00 中具有值2 对于第二周,列S在 2004/6/25 14:00 中具有值1,在 2004/6/21 18:00

中具有值2。

我想出了四个规则:

1。。当当前周内A = max(A)时,将值1放入S。如果一周内A最大值不是唯一的,则在最后一次出现S时将S放入1。 A中的最大值。

2。。当当前周内B = min(B)时,将值2放入S。如果一周内B最小值不是唯一的,则在最后一次出现B时将S放入2。 B中的最小值。

3。。请在整周内重复一次。整个数据集每小时可能有80k以上的数据行。

4。:在每周内:如果max(A)和min(B)在同一日期时间索引处出现,则将值0保留为S(不变)。

以下是读取数据的代码:

import pandas as pd

url = 'https://www.dropbox.com/s/x7wl75rkzsqgkoj/dataset.csv?dl=1'

p = pd.read_csv(url)
p.set_index('datetime', drop=True, inplace=True)
p

这是一张图片,解释了我希望输出如何: Final dataframe explanation

2 个答案:

答案 0 :(得分:3)

因此,我减小了数据框的大小,以便可以看到一些内容,并添加了列周(“ w”),以便我们更好地进行检查。

首先,您需要将索引的类型设置为datetime对象,以便可以访问日期属性,例如,星期几到groupby。

p.index = pd.to_datetime(p.index)
p["w"] = p.index.week 

p                                                                      
                         A      B  S   w
datetime                                
2004-06-14 01:00:00  384.5  383.6  0  25
2004-06-14 09:00:00  382.8  382.1  0  25
2004-06-14 17:00:00  384.8  382.5  0  25
2004-06-15 01:00:00  383.3  382.6  0  25
2004-06-15 09:00:00  382.3  381.6  0  25
2004-06-15 17:00:00  388.6  384.6  0  25
2004-06-16 01:00:00  387.3  387.1  0  25
2004-06-16 09:00:00  388.8  387.6  0  25
2004-06-16 17:00:00  384.5  382.6  0  25
2004-06-17 01:00:00  384.6  383.6  0  25
2004-06-17 09:00:00  385.6  384.0  0  25
2004-06-17 17:00:00  386.8  386.0  0  25
2004-06-18 01:00:00  388.6  387.3  0  25
2004-06-18 09:00:00  387.5  385.8  0  25
2004-06-18 17:00:00  395.8  394.1  0  25
2004-06-21 02:00:00  394.3  392.8  0  26
2004-06-21 10:00:00  393.3  392.3  0  26
2004-06-21 18:00:00  394.8  392.1  0  26
2004-06-22 02:00:00  394.6  393.0  0  26
2004-06-22 10:00:00  394.0  392.6  0  26
2004-06-22 18:00:00  395.3  393.8  0  26
2004-06-23 02:00:00  394.3  393.6  0  26
2004-06-23 10:00:00  395.8  395.0  0  26
2004-06-23 18:00:00  394.6  393.6  0  26
2004-06-24 02:00:00  394.6  393.1  0  26
2004-06-24 10:00:00  397.8  394.8  0  26
2004-06-24 18:00:00  401.3  400.6  0  26
2004-06-25 02:00:00  402.1  400.1  0  26
2004-06-25 10:00:00  401.8  400.8  0  26
2004-06-25 18:00:00  402.1  400.8  0  26
2004-06-28 03:00:00  402.3  401.5  0  27
2004-06-28 11:00:00  402.1  400.8  0  27
2004-06-28 19:00:00  400.3  399.1  0  27
2004-06-29 03:00:00  399.6  399.1  0  27
2004-06-29 11:00:00  397.1  395.3  0  27
2004-06-29 19:00:00  392.3  391.0  0  27
2004-06-30 03:00:00  392.3  391.8  0  27
2004-06-30 11:00:00  393.6  393.1  0  27
2004-06-30 19:00:00  393.5  391.3  0  27

然后,您需要定义每周要应用的功能:

def minmax(grp): 
    Amax = grp.A[::-1].idxmax() # reverse your Series since you want the last occurence, and idxmax return the first in case of tie 
    grp.loc[Amax, "S"] = 1  
    Bmin = grp.B[::-1].idxmin()
    if Bmin != Amax:  
        grp.loc[Bmin, "S"] = 2
    else:
        grp.loc[Bmin, "S"] = 0 # no change
    return grp 

,然后每年每年的一周进行分组,并应用功能:

p.groupby([p.index.week, p.index.year]).apply(minmax)                                 
                         A      B  S   w
datetime                                
2004-06-14 01:00:00  384.5  383.6  0  25
2004-06-14 09:00:00  382.8  382.1  0  25
2004-06-14 17:00:00  384.8  382.5  0  25
2004-06-15 01:00:00  383.3  382.6  0  25
2004-06-15 09:00:00  382.3  381.6  2  25
2004-06-15 17:00:00  388.6  384.6  0  25
2004-06-16 01:00:00  387.3  387.1  0  25
2004-06-16 09:00:00  388.8  387.6  0  25
2004-06-16 17:00:00  384.5  382.6  0  25
2004-06-17 01:00:00  384.6  383.6  0  25
2004-06-17 09:00:00  385.6  384.0  0  25
2004-06-17 17:00:00  386.8  386.0  0  25
2004-06-18 01:00:00  388.6  387.3  0  25
2004-06-18 09:00:00  387.5  385.8  0  25
2004-06-18 17:00:00  395.8  394.1  1  25
2004-06-21 02:00:00  394.3  392.8  0  26
2004-06-21 10:00:00  393.3  392.3  0  26
2004-06-21 18:00:00  394.8  392.1  2  26
2004-06-22 02:00:00  394.6  393.0  0  26
2004-06-22 10:00:00  394.0  392.6  0  26
2004-06-22 18:00:00  395.3  393.8  0  26
2004-06-23 02:00:00  394.3  393.6  0  26
2004-06-23 10:00:00  395.8  395.0  0  26
2004-06-23 18:00:00  394.6  393.6  0  26
2004-06-24 02:00:00  394.6  393.1  0  26
2004-06-24 10:00:00  397.8  394.8  0  26
2004-06-24 18:00:00  401.3  400.6  0  26
2004-06-25 02:00:00  402.1  400.1  0  26
2004-06-25 10:00:00  401.8  400.8  0  26
2004-06-25 18:00:00  402.1  400.8  1  26
2004-06-28 03:00:00  402.3  401.5  1  27
2004-06-28 11:00:00  402.1  400.8  0  27
2004-06-28 19:00:00  400.3  399.1  0  27
2004-06-29 03:00:00  399.6  399.1  0  27
2004-06-29 11:00:00  397.1  395.3  0  27
2004-06-29 19:00:00  392.3  391.0  2  27
2004-06-30 03:00:00  392.3  391.8  0  27
2004-06-30 11:00:00  393.6  393.1  0  27
2004-06-30 19:00:00  393.5  391.3  0  27

HTH

答案 1 :(得分:1)

非常类似于@jrjc方法,但是我认为这可以在没有分配的情况下完成,让我们尝试一下:

def f(x):
    x.loc[x['A'][::-1].idxmax(), 'S'] = 1
    lindx = x['B'][::-1].idxmin()
    x.loc[lindx, 'S'] = np.where(x.loc[lindx, 'S'] == 1, 0, 2)
    return x


p_out = p.groupby(pd.Grouper(freq='W')).apply(f)

通过仅查看p_out的S的非零值来检查输出:

p_out[p_out.S.ne(0)]

输出:

                         A      B  S
datetime                            
2004-06-15 11:00:00  382.0  381.1  2
2004-06-18 18:00:00  395.8  394.1  1
2004-06-21 18:00:00  394.8  392.1  2
2004-06-25 14:00:00  402.8  401.0  1
2004-06-28 14:00:00  404.6  402.3  1
2004-06-29 17:00:00  394.5  390.3  2