我正在考虑像小时这样的小时降水数据。
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以及如何使我的代码更有效?
提前致谢, 阿克塞尔
答案 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