Векторизация операции условного обновления в Pandas - PullRequest
1 голос
/ 05 мая 2020

Мой первый вопрос! Мне нужна помощь в том, как векторизовать операцию в кадре данных pandas. Я могу упростить задачу до фрейма данных с тремя столбцами, столбцом со значениями, которые будут обновлены, и двумя столбцами с номером итерации, который не совпадает между двумя столбцами.

Что я Я бы хотел сделать, чтобы один из столбцов итерации для каждого из первых значений в столбце итерации затем ссылался на соответствующее значение другого столбца итерации (с тем же индексом), а затем, наконец, для заполнения значения (ноль) в столбец со значениями обновления, но только для строк, в которых второй столбец итерации имеет такое же значение. Надеюсь, этот пример объяснит немного лучше:

df = pd.DataFrame()
df['update_col'] = [1, 2, 3, 4, 5, 6, 7, 8, 9]
df['iter2'] = [0, 1, 1, 2, 2, 3, 3, 4, 4]
df['iter1'] = [0, 0, 1, 1, 1, 2, 2, 2, 2]

print(df)
#     update_col    iter2     iter1
0              1        0         0
1              2        1         0
2              3        1         1
3              4        2         1
4              5        2         1
5              6        3         2
6              7        3         2
7              8        4         2
8              9        4         2

Итак, в основном, я хочу сделать следующее:

  1. Ссылка на столбец iter1 и при его изменении (т.е. От 0 до 1 или от 1 до 2)
  2. Посмотрите на столбец iter2 по этому индексу
  3. Измените значения в «столбце обновления» на ноль для всех строк, начиная с индекса на шаге 2 пока iter2 не увеличится до нового значения

Таким образом, результат будет выглядеть следующим образом:

#     update_col    iter2     iter1
0              1        0         0
1              2        1         0
2              0        1         1
3              4        2         1
4              5        2         1
5              0        3         2
6              0        3         2
7              8        4         2
8              9        4         2

Я думаю, правильно построенный groupby может быть решением, но я Я до сих пор ладья ie в эффективном использовании.

В настоящее время я достигаю того, чего хочу, с помощью сложного для l oop, это делает время выполнения чрезвычайно длинным для размера и количества фреймов данных, с которыми я должен это сделать. Я думаю, что другим решением может быть операция map или replace, но усложняющее предостережение заключается в том, что я не хочу обновлять все значения для этого значения iter2, а только значения из этого индекса iter 1 до последнее из этих значений в iter2.

Любая помощь или понимание приветствуются!

1 Ответ

0 голосов
/ 05 мая 2020

Возможно, это не большое улучшение по сравнению с l oop, которое вы уже определили, но я думаю, что это избавляет от необходимости использовать вложенный l oop по крайней мере:

import pandas as pd

# creating data frame
df = pd.DataFrame()
df['update_col'] = [1, 2, 3, 4, 5, 6, 7, 8, 9]
df['iter2'] = [0, 1, 1, 2, 2, 3, 3, 4, 4]
df['iter1'] = [0, 0, 1, 1, 1, 2, 2, 2, 2]

# computing difference from prev element by creating a shifted col 
# and subtracting from the original.
# (you could also use a rolling window function for this)
df['change1'] = df['iter1'] - df['iter1'].shift(1)
df['change2'] = df['iter2'] - df['iter2'].shift(1)

# creating boolean cols to flag if iter1 or iter2 have changed
df['start'] = df['change1'] == 1
df['stop'] = df['change2'] == 1

# list to store result: if True, you update value to 0
res = [False] * len(df['start'])

for i in range(0, len(df['start'])):
    if df['start'][i]:
        #print('start detected')
        res[i] = True
    elif i > 1 and (not df['stop'][i]) and res[i-1]: 
        #print('continuation detected')
        res[i] = True
    #print(f'set res[{i}] to ', res[i])

df['update_to_zero'] = res

Результат в этом df:

   update_col  iter2  iter1  change1  change2  start   stop  update_to_zero
0           1      0      0      NaN      NaN  False  False           False
1           2      1      0      0.0      1.0  False   True           False
2           3      1      1      1.0      0.0   True  False            True
3           4      2      1      0.0      1.0  False   True           False
4           5      2      1      0.0      0.0  False  False           False
5           6      3      2      1.0      1.0   True   True            True
6           7      3      2      0.0      0.0  False  False            True
7           8      4      2      0.0      1.0  False   True           False
8           9      4      2      0.0      0.0  False  False           False

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...