pandas数据框:查找连续值并忽略特定大小的间隙

时间:2016-08-05 13:34:21

标签: python pandas dataframe

我正在考虑像小时这样的小时降水数据。

index=pd.date_range('1/1/2011', periods=365*24, freq='H')
precipitation_indicator=np.random.randint(low=0, high=2, size=(365*24,))
precipitation_sum=np.random.ranf((365*24,))*6*precipitation_indicator

prec_dataH=pd.DataFrame(data={'prec_ind':precipitation_indicator, prec_sum':precipitation_sum},index=index)

如果连续时间点有降水,我想要定义降雨事件,但是如果在一个事件中存在一定长度的间隙。 我使用以下代码

通过滚动窗口解决了这个问题
gap_to_ignore=1  
prec_dataH['event_ind']=prec_dataH['prec_ind'].rolling(window=(1+2*gap_to_ignore), center=True).max().dropna()

通过这样做,每当有降雨时,我会得到一个event_ind为1,并且在rainevent中也会有2小时的休息时间,但也会提前1小时和时间后1小时给出时间戳。我现在想要提前1小时和在rainevent之后删除这个。我通过

进行了管理

1。)为event_ind中的每个变化提供一个连续的数字

prec_dataH['event_no'] = (prec_dataH['event_ind'].shift(1) != prec_dataH['event_ind']).astype(int).cumsum()

2.。)为干活期分配event_no的NaN值

def reorder_eventNumbers_dryStart (event_numbers):
    if event_numbers % 2 !=0:
        return event_numbers/2
    else:
        return np.NaN

def reorder_eventNumbers_rainStart (event_numbers):
    if event_numbers % 2 ==0:
        return event_numbers/2
    else:
        return np.NaN

if prec_dataH.ix[1, 'event_ind']==1.:

    prec_dataH['event_no']=prec_dataH['event_no'].apply(reorder_eventNumbers_rainStart)
elif prec_dataH.ix[1, 'event_ind']==0.:
    prec_dataH['event_no']=prec_dataH['event_no'].apply(reorder_eventNumbers_dryStart)

3。)通过event_no进行分组,迭代组并在提前1小时和降水事件后1小时将NaN值分配给值,最后将组连接到新的DataFrame。

这是非常耗时的,因此会发生SettingWighCopyWarning,我不明白为什么会这样。

A value is trying to be set on a copy of a slice from a DataFrame.

以下是我使用的代码:

rainEvents=prec_dataH.groupby('event_no')

groups=[]
for name, group in rainEvents:
    group.ix[0:gap_to_ignore,'event_ind'] =np.NaN
    group.ix[0:gap_to_ignore,'event_no'] =np.NaN
    group.ix[-gap_to_ignore:, 'event_ind']=np.NaN
    group.ix[-gap_to_ignore:,'event_no'] =np.NaN
    groups.append(group)

rainEvents_corrected=pd.concat(groups)

那么如何避免这种SettingWithCopyWarning以及如何使我的代码更有效?

提前致谢, 阿克塞尔

1 个答案:

答案 0 :(得分:1)

添加group = group.copy()作为for循环中的第一行。这摆脱了SettingWithCopyWarning并将计算速度提高了约60倍。

def approach1():
    rainEvents=prec_dataH.groupby('event_no')

    groups=[]
    for name, group in rainEvents:
        group.ix[0:gap_to_ignore,'event_ind'] =np.NaN
        group.ix[0:gap_to_ignore,'event_no'] =np.NaN
        group.ix[-gap_to_ignore:, 'event_ind']=np.NaN
        group.ix[-gap_to_ignore:,'event_no'] =np.NaN
        groups.append(group)

    rainEvents_corrected=pd.concat(groups)


def approach2():
    rainEvents=prec_dataH.groupby('event_no')

    groups=[]
    for name, group in rainEvents:
        group = group.copy()
        group.ix[0:gap_to_ignore,'event_ind'] =np.NaN
        group.ix[0:gap_to_ignore,'event_no'] =np.NaN
        group.ix[-gap_to_ignore:, 'event_ind']=np.NaN
        group.ix[-gap_to_ignore:,'event_no'] =np.NaN
        groups.append(group)

    rainEvents_corrected=pd.concat(groups)

%timeit approach1()    # => 1 loop, best of 3: 1min 29s per loop
%timeit approach2()    # => 1 loop, best of 3: 1.42 s per loop

您可以使用for对象上的.apply()使用适当的函数(基本上模仿groupby循环的正文)来避免for循环。它似乎提供了相对于上述速度20-30%的加速。

def approach3():
    def correct_rainEvents(g):
        g.ix[:gap_to_ignore, ['event_ind', 'event_no']] = np.nan
        g.ix[-gap_to_ignore:, ['event_ind', 'event_no']] = np.nan
        return g

    rainEvents_corrected = (prec_dataH.groupby('event_no')
                                      .apply(correct_rainEvents)
                                      .reset_index(level='event_no', drop=True))

%timeit approach3()    # => 1 loop, best of 3: 1.12 s per loop