Так что у меня есть проблема в основном с производительностью, поскольку я могу вывести ожидаемый результат, но это занимает много времени. Я ищу более эффективные способы сделать следующее, что приведет к более быстрой реализации.
Проблема заключается в заполнении нулями в pandas DataFrame по строкам, но с учетом индекса начала и конца для каждого столбца (поэтому цель состоит не в том, чтобы заполнить весь столбец, а только между предоставленными индексами)
Пример:
Мы начинаем с определения нашего фрейма данных, который должен быть заполнен, и другого с индексами для каждой строки
a = pd.DataFrame(index=range(3), columns=range(10))
values = {0: [3, 7], 1: [2, 4], 2: [1, 5]}
for k, v in values.items():
a.iloc[k, v] = 1
b = pd.DataFrame({'start': [1, 2, 1], 'end': [7,6,8]})
>>>a
0 1 2 3 4 5 6 7 8 9
0 NaN NaN NaN 1 NaN NaN NaN 1 NaN NaN
1 NaN NaN 1 NaN 1 NaN NaN NaN NaN NaN
2 NaN 1 NaN NaN NaN 1 NaN NaN NaN NaN
>>>b
start end
0 1 7
1 2 6
2 1 8
Ожидаемый результат (конечный индекс не включается)
0 1 2 3 4 5 6 7 8 9
0 NaN 0.0 0 1 0 0 0.0 1.0 NaN NaN
1 NaN NaN 1 0 1 0 NaN NaN NaN NaN
2 NaN 1.0 0 0 0 1 0.0 0.0 NaN NaN
В настоящий момент я создал функцию, которая берет zip из каждой строки в кадре данных, выполняет заполнение строки и возвращает ее возвращает значения, а затем я воссоздаю фрейм данных
def _fill_slice(row_ind, value=0):
row, ind = row_ind
row[1].iloc[int(ind[0]):int(ind[1])].fillna(value, inplace=True)
return row[1].values
>>>pd.DataFrame(map(_fill_slice, zip(a.iterrows(), b.values)))
0 1 2 3 4 5 6 7 8 9
0 NaN 0.0 0 1 0 0 0.0 1.0 NaN NaN
1 NaN NaN 1 0 1 0 NaN NaN NaN NaN
2 NaN 1.0 0 0 0 1 0.0 0.0 NaN NaN
Это позволяет мне позже отправлять строки в несколько процессов через imap
pd.DataFrame(pool.imap(_fill_slice, zip(a.iterrows(), b.values), chunksize=chunksize))
В данный момент моя производительность составляет ~ 15 минут для ~ 4M строк, но я чувствую, что должен быть лучший способ сделать это.
Одно из решений, которое я собираюсь попробовать, состоит в том, чтобы сгруппировать одинаковые начало и конец и передать фрагменты объекта. тасет в каждый раз. Другая возможность состоит в том, чтобы запустить два цикла с вышеупомянутой идеей разбиения на части, заполнив все до конечных индексов, а затем вернув np.nan до начальных индексов. Это может уменьшить количество общих итераций.
Есть еще идеи? Заранее спасибо.