遍历DataFrame并跟踪一定的序列持续时间

时间:2018-06-27 09:19:14

标签: python pandas series

我想弄清楚负值出现的频率和负价出现的时间。

示例df

d = {'value': [1,2,-3,-4,-5,6,7,8,-9,-10], 'period':[1,2,3,4,5,6,7,8,10]}
df = pd.DataFrame(data=d)

我检查了哪些行具有负值。 df['value'] < 0

我想我可以遍历每一行,为出现负值时保留一个计数器,并且可以将该行移至另一个df,因为我想保存开头period和结尾{{1} }。

我目前正在尝试什么

period

我认为这给了我无限循环。如果我将def count_negatives(df): df_negatives = pd.DataFrame(columns=['start','end', 'counter']) for index, row in df.iterrows(): counter = 0 df_negative_index = 0 while(row['value'] < 0): # if its the first one add it to df as start ? # grab the last one and add it as end #constantly overwrite the counter? counter += 1 #add counter to df row df_negatives['counter'] = counter return df_negatives 替换为while,我就会想出一种跟踪多长时间的方法。

2 个答案:

答案 0 :(得分:2)

我认为更好的是避免循环:

#compare by < 
a = df['value'].lt(0)
#running sum
b = a.cumsum()
#counter only for negative consecutive values
df['counter'] = b-b.mask(a).ffill().fillna(0).astype(int)
print (df)
   value  period  counter
0      1       1        0
1      2       2        0
2     -3       3        1
3     -4       4        2
4     -5       5        3
5      6       6        0
6      7       7        0
7      8       8        0
8     -9       9        1
9    -10      10        2

或者如果不需要重置计数器:

a = df['value'].lt(0)
#repalce values per mask a to 0
df['counter'] = a.cumsum().where(a, 0)
print (df)
   value  period  counter
0      1       1        0
1      2       2        0
2     -3       3        1
3     -4       4        2
4     -5       5        3
5      6       6        0
6      7       7        0
7      8       8        0
8     -9       9        4
9    -10      10        5

如果需要开始和结束时间:

#comapre for negative mask
a = df['value'].lt(0)
#inverted mask
b = (~a).cumsum()

#filter only negative rows
c = b[a].reset_index()

#aggregate first and last value per groups
df = (c.groupby('value')['index']
       .agg([('start', 'first'),('end', 'last')])
       .reset_index(drop=True))
print (df)
   start  end
0      2    4
1      8    9

答案 1 :(得分:1)

  

我想保存开始时间和结束时间。

如果这是您的要求,则可以使用itertools.groupby。还请注意,period系列不是必需的,因为如果未明确提供,Pandas会提供自然的整数索引(从0开始)。

from itertools import groupby
from operator import itemgetter

d = {'value': [1,2,-3,-4,-5,6,7,8,-9,-10]}
df = pd.DataFrame(data=d)

ranges = []
for k, g in groupby(enumerate(df['value'][df['value'] < 0].index), lambda x: x[0]-x[1]):
    group = list(map(itemgetter(1), g))
    ranges.append((group[0], group[-1]))

print(ranges)

[(2, 4), (8, 9)]

然后,转换为数据框:

df = pd.DataFrame(ranges, columns=['start', 'end'])

print(df)

   start  end
0      2    4
1      8    9