Инициализировать значения для первой и последней строки после операции повторной выборки? - PullRequest
1 голос
/ 03 апреля 2020

Учитывая, например, DataFrame с 1h Period, я хотел бы установить значения 0 & 1 в новом столбце всякий раз, когда новый 5h Period начинается и заканчивается соответственно.

Давайте рассмотрим эти входные данные например:

import pandas as pd
from random import seed, randint
from collections import OrderedDict

p1h = pd.period_range(start='2020-02-01 00:00', end='2020-03-04 00:00', freq='1h', name='p1h')

seed(1)
values = [randint(0,10) for p in p1h]
df = pd.DataFrame({'Values' : values}, index=p1h)

Результат

df.head(10)

                  Values
p1h                     
2020-02-01 00:00       2
2020-02-01 01:00       9
2020-02-01 02:00       1
2020-02-01 03:00       4
2020-02-01 04:00       1
2020-02-01 05:00       7
2020-02-01 06:00       7
2020-02-01 07:00       7
2020-02-01 08:00      10
2020-02-01 09:00       6

Есть ли способ настроить новый столбец, чтобы получить следующий результат? (1-я и последняя строка для каждого периода инициализируются соответственно 0 и 1)

df['period5h'] = df.resample('5h').???

df.head(10)

                  Values   period5h
p1h                     
2020-02-01 00:00       2          0   <- 1st row of 5h period
2020-02-01 01:00       9
2020-02-01 02:00       1
2020-02-01 03:00       4
2020-02-01 04:00       1          1   <- last row of 5h period
2020-02-01 05:00       7          0   <- 1st row of 5h period
2020-02-01 06:00       7
2020-02-01 07:00       7
2020-02-01 08:00      10
2020-02-01 09:00       6          1   <- last row of 5h period

Пожалуйста, можно ли это как-то сделать с некоторыми функциями в pandas?

Конечная цель состоит в том, чтобы заполнить пустые значения путем линейной интерполяции между 0 и 1, чтобы получить прогресс в% текущей строки по отношению к 5-часовому периоду.

Другой трек / вопрос

Другой подход может состоять в том, чтобы инициализировать 2-й DataFrame с 5h PeriodIndex, инициализировать значения нового столбца в 1, а затем увеличить PeriodIndex обратно до 1H, чтобы объединить оба DataFrames.

A shift (-1) будет инициализировать последнюю строку периода.

Я бы повторил процесс без сдвига для значения 0.

Затем, как я могу создать этот новый DataFrame так, чтобы Я могу слить это с 1-го? Я попробовал несколько команд слияния, но у меня есть ошибка, указывающая, что оба индекса не имеют одинаковую частоту.

Спасибо за вашу помощь! Bests

Ответы [ 3 ]

1 голос
/ 03 апреля 2020

Используйте атрибут indices объекта с передискретизацией, чтобы найти первый и последний индексы групп. Это будет работать, даже если данные не имеют регулярную частоту или имеют частоту, которая не разделяет частоту повторной дискретизации. Группы будут иметь только одно измерение, установленное на 1 вместо 0. Затем мы устанавливаем значения соответственно

i1 = [] # Last `.iloc` index labels
i0 = [] # First `.iloc` index labels
for k,v in df.resample('5H').indices.items():
    i0.append(v[0])
    i1.append(v[-1])

df.loc[df.index[i0], 'period_5H'] = 0
df.loc[df.index[i1], 'period_5H'] = 1

                  Values  period_5H
p1h                                
2020-02-01 00:00       2        0.0
2020-02-01 01:00       9        NaN
2020-02-01 02:00       1        NaN
2020-02-01 03:00       4        NaN
2020-02-01 04:00       1        1.0
2020-02-01 05:00       7        0.0
2020-02-01 06:00       7        NaN
2020-02-01 07:00       7        NaN
2020-02-01 08:00      10        NaN
2020-02-01 09:00       6        1.0
2020-02-01 10:00       3        0.0
...
1 голос
/ 03 апреля 2020

Хорошо, я наконец-то настроился на использование следующего подхода, который довольно быстр (нет l oop)

 super_pi = pd.period_range(start='2020-01-01 00:00', end='2020-06-01 00:00', freq='5h', name='p5h')
 super_df = pd.DataFrame({'End' : 1, 'Start' : 0}, index=super_pi).resample('1h').first()
 # We know last row is a 1 (end of period)
 super_df['End'] = super_df['End'].shift(-1, fill_value=1)
 super_df['Period'] = super_df[['End','Start']].sum(axis=1, min_count=1)

Результат

 supder_df.head(10)

                   End  Start  Period
 p5h                                 
 2020-01-01 00:00  NaN    0.0     0.0
 2020-01-01 01:00  NaN    NaN     NaN
 2020-01-01 02:00  NaN    NaN     NaN
 2020-01-01 03:00  NaN    NaN     NaN
 2020-01-01 04:00  1.0    NaN     1.0
 2020-01-01 05:00  NaN    0.0     0.0
 2020-01-01 06:00  NaN    NaN     NaN
 2020-01-01 07:00  NaN    NaN     NaN
 2020-01-01 08:00  NaN    NaN     NaN

Bests,

1 голос
/ 03 апреля 2020

Не большинство pythoni c подход, но он работает.

import pandas as pd
from random import seed, randint
from collections import OrderedDict
import time
p1h = pd.period_range(start='2020-02-01 00:00', end='2040-03-04 00:00', freq='1h', name='p1h')

seed(1)
values = [randint(0,10) for p in p1h]
df = pd.DataFrame({'Values' : values}, index=p1h)

t1 = time.time()
for i in range(len(df['Values'])):
  if (i+1)% 5 == 1:
    df['Values'].iloc[i] = 0
  elif (i+1) % 5 == 0:
    df['Values'].iloc[i] = 1
t2 = time.time()
df.head(20)

print(t2-t1)


время: 8.770591259002686

Подход 2:

import pandas as pd
from random import seed, randint
from collections import OrderedDict
import time
p1h = pd.period_range(start='2020-02-01 00:00', end='2040-03-04 00:00', freq='1h', name='p1h')

seed(1)
values = [randint(0,10) for p in p1h]
df = pd.DataFrame({'Values' : values}, index=p1h)

t1 = time.time()

df['Values'].iloc[range(0,len(df['Values']),5)] = 0
df['Values'].iloc[range(4,len(df['Values']),5)] = 1
t2 = time.time()
df.head(20)

print(t2-t1)

время: 0.009400367736816406

...