Возвращение самой высокой и самой низкой корреляций из корреляционной матрицы в пандах

1

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

Допустим, матрица corr выглядит так:

  A    B    C    D    E
A 1.00 0.65 0.31 0.94 0.55
B 0.87 1.00 0.96 0.67 0.41
C 0.95 0.88 1.00 0.72 0.69
D 0.64 0.84 0.99 1.00 0.78
E 0.71 0.62 0.89 0.32 1.00

Что я хочу сделать, так это уметь вернуть две лучшие и наименее коррелированные акции и их корреляцию для акций A, B, C, D & E, упуская очевидную 1,00-корреляцию, которую каждая акция имеет с собой.

Результирующий кадр данных, или что-либо, что проще всего отобразить, будет выглядеть так:

Stock 1st 1st_Val 2nd 2nd_Val Last Last_Val
A     D   0.94    B   0.65    C    0.31
B     C   0.96    A   0.87    E    0.41
C     A   0.95    B   0.88    E    0.69
D     C   0.99    B   0.84    A    0.64
E     C   0.89    A   0.71    D    0.32

С моими попытками до сих пор я смог просмотреть и вернуть соответствующие названия акций, используя corr[stock].nlargest().index[0:].tolist(), а затем взяв [1], [2] и [-1] из каждого списка, вставляя их в словарь и создавая [-1]. Но я не могу вернуть значение корреляции и подозреваю, что в любом случае я делаю это не самым эффективным способом.

Любая помощь действительно ценится, ура

  • 1
    Разве корреляционная матрица не должна быть симметричной? Или ваш приведенный пример является просто примером матрицы?
  • 0
    корреляционные матрицы могут быть асимметричными, довольно распространенными в финансовых данных
Показать ещё 3 комментария
Теги:
pandas
correlation

3 ответа

0

Другой ответ, опирающийся больше на современный стиль панд. Я не нашел хорошего решения для второй по величине корреляции. Я отредактирую ответ, когда найду его.

### Create an example df
df = pd.DataFrame(data = {"A":pd.np.random.randn(10),
                    "B":pd.np.random.randn(10),
                    "C":pd.np.random.randn(10),
                    "D":pd.np.random.randn(10),
                        }
                )


# Solution
(
df.corr() #correlation matrix
  .replace(1, pd.np.nan) # replace the matrix with nans
  .assign(  # assign new variables
            First = lambda x: x.loc[["A","B","C","D"], ["A","B","C","D"]].idxmax(axis = 1), # Biggest correlation idx
            First_value = lambda x: x.loc[["A","B","C","D"], ["A","B","C","D"]].max(axis = 1), # Biggest correlation
            Last = lambda x: x.loc[["A","B","C","D"],["A","B","C","D"]].idxmin(axis = 1), # Smallest correlation idx
            Last_value = lambda x: x.loc[["A","B","C","D"],["A","B","C","D"]].idxmin(axis = 1), # Smallest correlation
              )
)

Я использую .loc[["A","B","C","D"],["A","B","C","D"]], что операции выполняются только на неизмененный фрейм данных.

Выход:
          A         B         C         D First  First_value Last Last_value
A       NaN -0.085776 -0.203110 -0.003450     D    -0.003450    C          C
B -0.085776       NaN -0.110402  0.687283     D     0.687283    C          C
C -0.203110 -0.110402       NaN  0.017644     D     0.017644    A          A
D -0.003450  0.687283  0.017644       NaN     B     0.687283    A          A
  • 0
    У вас есть опечатка для Last_value . Как вы могли бы расширить это, чтобы получить второе по величине значение? Кроме того, replace(1, np.nan) предполагает, что никакие две переменные не являются на 100% коррелированными (то есть предполагается, что нет недиагональных 1 с).
0

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

Убрать диагональ

import numpy as np
np.fill_diagonal(corr.values, np.nan)
print(corr)
#      A     B     C     D     E
#A   NaN  0.65  0.31  0.94  0.55
#B  0.87   NaN  0.96  0.67  0.41
#C  0.95  0.88   NaN  0.72  0.69
#D  0.64  0.84  0.99   NaN  0.78
#E  0.71  0.62  0.89  0.32   NaN

Найти имена топ-2 и нижних столбцов

Вы можете использовать ответ на Найти имена топ-n столбцов с наивысшими значениями в каждой строке кадра данных pandas, чтобы получить верхнее и нижнее одно значение для каждой строки (Stock).

order_top2 = np.argsort(-corr.values, axis=1)[:, :2]
order_bottom = np.argsort(corr.values, axis=1)[:, :1]

result_top2 = pd.DataFrame(
    corr.columns[order_top2], 
    columns=['1st', '2nd'],
    index=corr.index
)

result_bottom = pd.DataFrame(
    corr.columns[order_bottom], 
    columns=['Last'],
    index=corr.index
)

result = result_top2.join(result_bottom)
#  1st 2nd Last
#A   D   B    C
#B   C   A    E
#C   A   B    E
#D   C   B    A
#E   C   A    D

Теперь используйте pandas.DataFrame.lookup чтобы получить соответствующее значение столбца в corr для каждого столбца в result

for x in result.columns:
    result[x+"_Val"] = corr.lookup(corr.index, result[x])
print(result)
#  1st 2nd Last  1st_Val  2nd_Val  Last_Val
#A   D   B    C     0.94     0.65      0.31
#B   C   A    E     0.96     0.87      0.41
#C   A   B    E     0.95     0.88      0.69
#D   C   B    A     0.99     0.84      0.64
#E   C   A    D     0.89     0.71      0.32

Изменить порядок столбцов (необязательно)

print(result[['1st', '1st_Val', '2nd', '2nd_Val', 'Last', 'Last_Val']])
#  1st  1st_Val 2nd  2nd_Val Last  Last_Val
#A   D     0.94   B     0.65    C      0.31
#B   C     0.96   A     0.87    E      0.41
#C   A     0.95   B     0.88    E      0.69
#D   C     0.99   B     0.84    A      0.64
#E   C     0.89   A     0.71    D      0.32
0

Если вам нужно визуализировать результаты, но вам на самом деле не нужно извлекать и работать с фактическими значениями корреляции, то почему бы не использовать очень простую тепловую карту? Вы также можете поиграть с сюжетом, чтобы цифры отображались на каждом квадрате.

import seaborn as sns
import pandas as pd

 dict = {'Date':['2018-01-01','2018-01-02','2018-01-03','2018-01-04','2018-01-05'],'Col1':[1,2,3,4,5],'Col2':[1.1,1.2,1.3,1.4,1.5],'Col3':[0.33,0.98,1.54,0.01,0.99],'Col4':[8,9.98,6,0.01,0.1],'Col1':[19,42,3,0.4,51]}
df = pd.DataFrame(dict, columns=dict.keys())
sns.heatmap(df.corr())

Изображение 174551

  • 0
    Привет, приятель, извините, быстрый вопрос, sns.heatmap (df.corr ()) на самом деле ничего не делает для меня, так как я не использую jypiter, я просто использую pycharm, мне нужно сделать .show () или что-то еще ? Просто не вижу, чтобы показать карту тепла, ура
  • 0
    @topbantz Скорее всего, у вас есть решение здесь
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню