Корреляция временных рядов «один ко многим» в Python с очень большими размерностями

Моя база данных содержит 1 миллион уникальных терминов, которые были введены в поле поиска моего веб-сайта.

В настоящее время он содержит два столбца: поисковый запрос (пользовательский запрос) и объем (количество запросов поискового запроса, сделанных в данном месяце). База данных разбита на ежемесячные таблицы за последние 10 лет. Средний объем 18 в месяц. В некоторых поисковых запросах отсутствуют некоторые месячные разделы, если они не были запрошены ни одним пользователем.

Я хочу иметь возможность анализировать любой отдельный термин, чтобы быстро определить его наиболее значимые, коррелированные термины с использованием python.

Из-за ее размера создание всей корреляционной матрицы было бы расточительным с точки зрения памяти и ЦП.

Какая структура и функция фрейма данных лучше всего подходят для этого сравнения «один ко многим» в python? И потребует ли эта функция какой-либо детрендинг?


person Jonathan Francis    schedule 06.08.2020    source источник
comment
привет, мой ответ помог?   -  person RichieV    schedule 13.08.2020


Ответы (1)


Вы можете строить полную корреляционную матрицу каждый месяц или, возможно, не полную, а только список интересных терминов по принципу «несколько ко всем». Таким образом, у вас есть статистика, сохраненная в файле.

Если вы решите получить корреляцию «один ко всем» по запросу, вы можете, по крайней мере, создать DataFrame, который работает как кеш, сохраняя результат каждый раз, когда вы вычисляете корреляции одного термина.

Чтобы вычислить корреляцию одного термина со всеми остальными, вы можете использовать DataFrame.corrwith:

Скажем, у вас есть следующий df:

import string

terms_list = [''.join((a, b, c))
            for a in string.ascii_lowercase[:25]
            for b in string.ascii_lowercase[:20]
            for c in string.ascii_lowercase[:20]]
np.random.seed(1)
df = pd.Series(
    np.random.choice(list(np.arange(10, 26)) + [np.nan], int(120e4)),
    index = pd.MultiIndex.from_product([terms_list, range(120)],
        names=['term', 'month'])
    )
df = df.dropna().unstack()
pivot_term = terms_list[0]

печать (дф)

aaa    15.0  21.0  22.0  18.0  19.0  21.0  15.0  ...   NaN  15.0  23.0  11.0  20.0  10.0  17.0
aab    10.0  24.0  23.0  21.0  16.0  23.0  25.0  ...   NaN  15.0  12.0  11.0  21.0  15.0  19.0
aac    21.0  11.0  10.0  17.0  10.0  12.0  13.0  ...  10.0  10.0  25.0  14.0  20.0  22.0  15.0
aad     NaN  10.0  21.0  22.0  21.0  13.0  22.0  ...  11.0  17.0  12.0  14.0  15.0  17.0  22.0
aae    23.0  10.0  17.0  25.0  19.0  11.0  11.0  ...  10.0  25.0  18.0  16.0  10.0  16.0  11.0
...     ...   ...   ...   ...   ...   ...   ...  ...   ...   ...   ...   ...   ...   ...   ...
ytp    24.0  18.0  16.0  23.0   NaN  19.0  18.0  ...  20.0  15.0  21.0  11.0  14.0  18.0  19.0
ytq    22.0  11.0  17.0  24.0  12.0  20.0  17.0  ...  16.0   NaN  13.0  13.0  18.0  22.0  15.0
ytr    22.0  19.0  20.0  11.0  10.0  20.0  14.0  ...  24.0  21.0   NaN  19.0  10.0  24.0  22.0
yts    22.0   NaN  22.0  17.0  14.0  14.0  25.0  ...  14.0  22.0   NaN  23.0  14.0  25.0  10.0
ytt    17.0  16.0  15.0  21.0  11.0  19.0  16.0  ...  10.0  19.0  19.0  13.0  21.0  18.0  16.0

[10000 rows x 120 columns]

код

t1 = time()
max_periods = 120
df = df.iloc[:, -max_periods:]
### get correlations
corr = df.drop(pivot_term, axis=0).corrwith(df.loc[pivot_term], axis=1)
t1 = time() - t1
print(corr)
print(t1)

Выход

term
aab    0.045972
aac    0.064941
aad   -0.057009
aae   -0.187645
aaf   -0.075473
         ...
ytp    0.103756
ytq   -0.054769
ytr   -0.115004
yts    0.123223
ytt    0.230628
Length: 9999, dtype: float64
9.76

Отсюда вы можете отфильтровать интересные термины с помощью corr.nlargest или corr.nsmallest.

PS

Вы также можете рассмотреть меньший тип данных, который соответствует максимальному объему в месяц, скажем, np.int16.

person RichieV    schedule 07.08.2020
comment
Большое спасибо за этот невероятно вдумчивый ответ. - person Jonathan Francis; 27.08.2020