Панды: как исправить значения меньше предыдущих и некоторые паттерны - PullRequest
1 голос
/ 04 октября 2019

У меня есть следующий временной ряд:

2017-11-01 200.000000 2017-12-01 394.000000 2018-01-01 537.000000 2018-02-01 537.000000 2018-03-01 537.000000 2018-04-01 537.000000 2018-05-01 537.000000 2018-06-01 537.000000 2018-07-01 137.000000 2018-08-01 88.000000 2018-09-01 10.000000 2018-10-01 100.000000 2018-11-01 100.000000 2018-12-01 111.000000 2019-01-01 362.000000 2019-02-01 563.000000 2019-03-01 706.000000 2019-04-01 750.000000 2019-05-01 785.000000 2019-06-01 785.000000

Я имею дело с периодическим временным рядом, где значения накапливаются с сентября по август. В сентябре значение должно быть ниже предыдущего. Это не относится к предыдущим месяцам! Итак, мои временные ряды неверны в 2018-07-01 и 2018-08-01, но они верны в 2018-09-01. Я хочу заменить эти значения последним в 2018-06-01 (537.0).

Я использовал опцию .shift (1) pandas, но мне удалось только заменить июльские значения июньскими,но я заменил август предыдущим значением июля! Вот код, который я использовал:

new_df = pd.DataFrame({'date': new_df.index.tolist(), 'vals': new_df.tolist()}) # from df to ts
new_df['shift_values'] = new_df['vals'].shift(1) # create a col with previous values
new_df['diff'] = new_df.apply(lambda x: x['vals']-x['shift_values'], axis=1) # calculate the difference
new_df['valore_finale'] = new_df.apply(lambda x: x['vals'] if x['date'] == '2019-09-01' else(x['vals'] if x['diff']>0 else x['shift_values']), axis=1)

2017-11-01 200.000000 2017-12-01 394.000000 2018-01-01 537.000000 2018-02-01 537.000000 2018-03-01 537.000000 2018-04-01 537.000000 2018-05-01 537.000000 2018-06-01 537.000000 2018-07-01 537.000000 # changed 2018-08-01 537.000000 # changed 2018-09-01 10.000000 # no changed 2018-10-01 100.000000 2018-11-01 100.000000 2018-12-01 111.000000 2019-01-01 362.000000 2019-02-01 563.000000 2019-03-01 706.000000 2019-04-01 750.000000 2019-05-01 785.000000 2019-06-01 785.000000

Ответы [ 2 ]

0 голосов
/ 04 октября 2019

Я нашел решение, которое очень жадное, но работает!

results = [new_df.vals[0]]
new_value = 0

for index, values in new_df[1:].iterrows():
    if '09' not in str(values.date):  # if date is not September
        if values.vals < new_value:
            new_value = new_value
        else:
            new_value = values.vals
    else:
        new_value = values.vals
    results.append(new_value)

new_df['new_values'] = [r for r in results]

Надеюсь, кто-нибудь сможет найти что-то лучшее, используя панд.

0 голосов
/ 04 октября 2019

сначала преобразовать в дату и время, чтобы можно было использовать mask в зависимости от месяцев, которые вы хотите изменить:

df['date']=pd.to_datetime(df['date'])

Затем используйте Series.mask , чтобы указать как NaNзначения, которые вы хотите изменить, а затем заполните их Series.ffill

df['vals']=df['vals'].mask((df['date'].dt.month<9) & (df['vals']<df['vals'].shift())).ffill()
print(df)
         date   vals
0  2017-11-01  200.0
1  2017-12-01  394.0
2  2018-01-01  537.0
3  2018-02-01  537.0
4  2018-03-01  537.0
5  2018-04-01  537.0
6  2018-05-01  537.0
7  2018-06-01  537.0
8  2018-07-01  537.0
9  2018-08-01  537.0
10 2018-09-01   10.0
11 2018-10-01  100.0
12 2018-11-01  100.0
13 2018-12-01  111.0
14 2019-01-01  362.0
15 2019-02-01  563.0
16 2019-03-01  706.0
17 2019-04-01  750.0
18 2019-05-01  785.0
19 2019-06-01  785.0

, если для января значение декабря предыдущего года не должно приниматься во внимание, groupby должен использоваться.

g=df.groupby(df['date'].dt.year)['vals']
df['vals']=df['vals'].mask( (df['vals']<g.shift())&(df['date'].dt.month<9) ).ffill()

Подробности

Series.shift isиспользуется для сравнения с предыдущим.

datetime.dt.month используется для получения месяцев до сентября

...