Python - векторизованная сумма условных переменных, основанная на разнице дат в таблице строк на миллион - PullRequest
0 голосов
/ 10 июня 2018

У меня есть следующие панды Dataframe:

Date                         Variable
2018-04-10 21:05:00             a
2018-04-10 21:05:00             a
2018-04-10 21:10:00             b
2018-04-10 21:15:00             a
2018-04-10 21:35:00             b
2018-04-10 21:45:00             a
2018-04-10 21:45:00             a

Моя цель состоит в том, чтобы вычислить количество строк, содержащих, скажем, 'a', то есть за 30 минут до и 30 минут после каждого времени (включая строки содно и то же время до и после, но не включая каждую анализируемую строку).Затем сделайте то же самое для каждого Variable.Так что для Variable a я бы получил что-то вроде следующего:

Date                   nr_30_min_bef_a    nr_30_min_after_a   
2018-04-10 21:05:00           1                    2                             
2018-04-10 21:05:00           1                    2
2018-04-10 21:10:00           2                    1
2018-04-10 21:15:00           2                    2
2018-04-10 21:35:00           3                    2
2018-04-10 21:45:00           2                    1
2018-04-10 21:45:00           2                    1

Я попытался выполнить цикл for для итерации по всем строкам, проблема в том, что вся серияимеет более миллиона строк, поэтому я искал более эффективное решение.

import pandas as pd

df = pd.DataFrame({'Date': ['2018-04-10 21:05:00',
                            '2018-04-10 21:05:00',
                            '2018-04-10 21:10:00',
                            '2018-04-10 21:15:00',
                            '2018-04-10 21:35:00',
                            '2018-04-10 21:45:00',
                            '2018-04-10 21:45:00'],
                   'Variable': ['a', 'a', 'b', 'a', 'b', 'a', 'a']})

Заранее спасибо.

1 Ответ

0 голосов
/ 10 июня 2018

Используя этот предыдущий ответ , вы можете использовать

import pandas as pd

df = pd.DataFrame({'Date': ['2018-04-10 21:05:00',
                            '2018-04-10 21:05:00',
                            '2018-04-10 21:10:00',
                            '2018-04-10 21:15:00',
                            '2018-04-10 21:35:00',
                            '2018-04-10 21:45:00',
                            '2018-04-10 21:45:00'],
                   'Variable': ['a', 'a', 'b', 'a', 'b', 'a', 'a']})

df['Date'] = pd.to_datetime(df['Date'])

freq_table = pd.crosstab(index=df['Date'], columns=df['Variable'])
df_bef = freq_table.rolling('30T', closed='both').sum().astype(int)
is_current = (freq_table != 0).astype(int)
df_bef -= is_current
df_bef.columns = ['nr_30_min_bef_{}'.format(col) for col in df_bef.columns]
result = pd.merge(df, df_bef, left_on='Date', right_index=True)

max_date = df['Date'].max()
min_date = df['Date'].min()
pseudo_dates = (max_date - df['Date'])[::-1] + min_date
freq_table_reversed = pd.crosstab(index=pseudo_dates, columns=df['Variable'])
df_after = freq_table_reversed.rolling('30T', closed='both').sum().astype(int)
df_after = pd.DataFrame(df_after.values[::-1], index=freq_table.index, 
                       columns=df_after.columns)
df_after -= is_current
df_after.columns = ['nr_30_min_after_{}'.format(col) for col in df_after.columns]

result = pd.merge(result, df_after, left_on='Date', right_index=True)
print(result)

, который печатает

                 Date Variable  nr_30_min_bef_a  nr_30_min_bef_b  nr_30_min_after_a  nr_30_min_after_b
0 2018-04-10 21:05:00        a                1                0                  2                  2
1 2018-04-10 21:05:00        a                1                0                  2                  2
2 2018-04-10 21:10:00        b                2                0                  1                  1
3 2018-04-10 21:15:00        a                2                1                  2                  1
4 2018-04-10 21:35:00        b                3                1                  2                  0
5 2018-04-10 21:45:00        a                2                1                  1                  0
6 2018-04-10 21:45:00        a                2                1                  1                  0

Основная новая идея заключается в использовании pd.crosstab для генерации таблицы частот:

freq_table = pd.crosstab(index=df['Date'], columns=df['Variable'])
# Variable             a  b
# Date                     
# 2018-04-10 21:05:00  2  0
# 2018-04-10 21:10:00  0  1
# 2018-04-10 21:15:00  1  0
# 2018-04-10 21:35:00  0  1
# 2018-04-10 21:45:00  2  0

и затем суммирования чисел в каждом скользящем окне:

df_bef = freq_table.rolling('30T', closed='both').sum().astype(int)

Поскольку вы хотите исключить текущую строку из числа, is_currentвычитается из df_bef:

is_current = (freq_table != 0).astype(int)
df_bef -= is_current
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...