У меня есть неравномерно распределенные временные ряды, которые выполняют повторную выборку с чуть более высокой частотой (в данном случае 1min
), чтобы я мог выполнить некоторые вычисления. Теперь есть один столбец с именем minor
в примере, который несколько раз задерживается на несколько строк, иногда он корректно выравнивается. Мне нужно найти способ выровнять конец ненулевых блоков в 'minor' с концами ненулевых блоков в major
, как показано в примере:
major = [0,0,0,0,0,0,0,0,4,4,4,4,4,5,6,7,0,0,0,0,4,3,5,6,4,0,0,0]
minor = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,1,.9,0]
# correctly aligned minor row:
minor_aligned = [0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,1,.9,0,0,0]
df = pd.DataFrame(
data={'major': major, 'minor': minor, 'minor_aligned': minor_aligned})
df.index.name = 'index'
Ожидаемый результат:
Значения в minor
должны быть выровнены как в minor_aligned
.
Краткое объяснение:
Последнее ненулевое значение каждого последовательного блока ненулевых значений в minor
должно быть выровнено с последним ненулевым значением каждого блока в major
, как показано с помощью minor_aligned
. Применяются следующие дополнительные ограничения:
minor
будет ровно 1 в 95% времени (или 0), остальное будет несколько значений между ними.
minor
может быть только > 0
, где major > 0
- ненулевой блок в
minor
может быть не больше, чем соответствующий блок в major
, но никогда не дольше. Это будет в основном намного короче, чем блок в major
- Если соответствующего блока нет,
minor
должно быть 0
. (Я не нашел такого случая, поэтому это необязательно)
Что я пробовал до сих пор:
[Из этого поста] я скопировал метод подсчета block
, кроме того, я попытался реализовать некоторые маскировки и экспериментировал со всеми видами cumcount
, cumsum
и т. Д., Но я не смог найти решение.
df['mask_mult'] = pd.DataFrame( # mask where shifted rows exist
np.where((df.minor != 0.) & (df.major == 0.), 1 * df.minor, 0),
index=df.index, columns=['outliers'])
# block counting method:
df['block'] = (df.minor.shift(1) != df.minor).astype(int).cumsum()
df.loc[:, 'block'][df['minor'] == 0] = 0 # set zero-blocks to zero
Используя groupby, категории и агрегаты (понятия не имею, как правильно их использовать), я попытался использовать маски / блоки, но у меня ничего не получилось:
# make block counting categories:
df_cat = df.set_index(pd.cut(df.block, np.arange(-1, df.block.max() + 1)))
# groupby blocks and use mask as amount of shift indices:
df_grpd = df.groupby('block').sum()
Я подумал, что можно либо перебрать все категории в df_cat
, чтобы получить индексы сдвига, либо перебрать сгруппированные блоки в df_grpd
, чтобы сделать то же самое (и использовать суммированную mask
как число строк для сдвига) , но в обоих случаях я не получаю правильные результаты из-за значения 0.9
.
Есть идеи о том, как я могу сделать это с такими значениями, как 0.9
и, если возможно, полностью избегая циклов?
Заранее спасибо!