Как манипулировать блоками строк в пандах - PullRequest
0 голосов
/ 11 ноября 2018

У меня есть большая база данных (240 миллионов строк), разделенная на блоки, с отметкой начала блока (sob) в качестве одного из столбцов, 1,3 миллиона блоков.

Я создал серию block_start:

block_start = pd.series(df[df.sob == True].index)

и вычислите ряд длин блоков:

block_len = block_start.shift(-1) - block_start.

Теперь мне нужно выяснить, содержит ли каждый блок хотя бы один сигнал (true) в логическом столбце:

signals = []

for i in range(len(block_start)):
 signals.append(df.signal[block_start[i]:block_start[i]+block_len[i]].any())

Вышеуказанный цикл занимает 20 минут.Есть идеи как его укоротить?

Ответы [ 2 ]

0 голосов
/ 11 ноября 2018

Для невероятной производительности 1 вы можете позволить NumPy вступить во владение.
(Данные заимствованы из ответа @ jpp)

v = np.cumsum(df['sob'])
df['any_flag'] = v.isin(v[df.signal].unique())

print(df)
   signal    sob  any_flag
0    True   True      True
1   False  False      True
2    True  False      True
3   False  False      True
4   False   True      True
5   False  False      True
6    True  False      True
7   False   True     False
8   False  False     False
9   False  False     False

1. Ваш пробег может варьироваться.


df = pd.concat([df] * 10000, ignore_index=True)

%timeit df['any_flag'] = (
    df.groupby(df['sob'].cumsum())['signal'].transform('any'))
%%timeit 
v = np.cumsum(df['sob'])
df['any_flag'] = v.isin(v[df.signal].unique())

10.9 ms ± 610 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
4.5 ms ± 19.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
0 голосов
/ 11 ноября 2018

groupby + cumsum + any

Вы можете groupby совокупная сумма вашей sob серии:

df = pd.DataFrame({'signal': [True, False, True, False, False,
                              False, True, False, False, False],
                   'sob': [True, False, False, False, True,
                           False, False, True, False, False]})

df['any_flag'] = df.groupby(df['sob'].cumsum())['signal'].transform('any')

print(df)

   signal    sob  any_flag
0    True   True      True
1   False  False      True
2    True  False      True
3   False  False      True
4   False   True      True
5   False  False      True
6    True  False      True
7   False   True     False
8   False  False     False
9   False  False     False
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...