Перелічити найвищі пари кореляції з великої кореляційної матриці у панд?


96

Як знайти найкращі кореляції в кореляційній матриці з Пандами? Є багато відповідей про те, як це зробити за допомогою R ( Показати кореляції як упорядкований список, а не як велику матрицю або Ефективний спосіб отримати висококорельовані пари з великого набору даних у Python або R ), але мені цікаво, як це зробити з пандами? У моєму випадку матриця має формат 4460x4460, тому не можу зробити це візуально.

Відповіді:


92

Ви можете використовувати, DataFrame.valuesщоб отримати масив numpy даних, а потім використовувати функції NumPy, такі як argsort()отримати найбільш корельовані пари.

Але якщо ви хочете зробити це в пандах, ви можете unstackвідсортувати DataFrame:

import pandas as pd
import numpy as np

shape = (50, 4460)

data = np.random.normal(size=shape)

data[:, 1000] += data[:, 2000]

df = pd.DataFrame(data)

c = df.corr().abs()

s = c.unstack()
so = s.sort_values(kind="quicksort")

print so[-4470:-4460]

Ось результат:

2192  1522    0.636198
1522  2192    0.636198
3677  2027    0.641817
2027  3677    0.641817
242   130     0.646760
130   242     0.646760
1171  2733    0.670048
2733  1171    0.670048
1000  2000    0.742340
2000  1000    0.742340
dtype: float64

10
У Pandas v 0.17.0 і новіших версій замість порядку слід використовувати сортування_значень. Якщо ви спробуєте скористатися методом замовлення, ви отримаєте повідомлення про помилку.
Friendm1,

46

Відповідь @ HYRY ідеальна. Просто спираючись на цю відповідь, додавши трохи більше логіки, щоб уникнути дублікатів та самостійних кореляцій та правильного сортування:

import pandas as pd
d = {'x1': [1, 4, 4, 5, 6], 
     'x2': [0, 0, 8, 2, 4], 
     'x3': [2, 8, 8, 10, 12], 
     'x4': [-1, -4, -4, -4, -5]}
df = pd.DataFrame(data = d)
print("Data Frame")
print(df)
print()

print("Correlation Matrix")
print(df.corr())
print()

def get_redundant_pairs(df):
    '''Get diagonal and lower triangular pairs of correlation matrix'''
    pairs_to_drop = set()
    cols = df.columns
    for i in range(0, df.shape[1]):
        for j in range(0, i+1):
            pairs_to_drop.add((cols[i], cols[j]))
    return pairs_to_drop

def get_top_abs_correlations(df, n=5):
    au_corr = df.corr().abs().unstack()
    labels_to_drop = get_redundant_pairs(df)
    au_corr = au_corr.drop(labels=labels_to_drop).sort_values(ascending=False)
    return au_corr[0:n]

print("Top Absolute Correlations")
print(get_top_abs_correlations(df, 3))

Це дає такий результат:

Data Frame
   x1  x2  x3  x4
0   1   0   2  -1
1   4   0   8  -4
2   4   8   8  -4
3   5   2  10  -4
4   6   4  12  -5

Correlation Matrix
          x1        x2        x3        x4
x1  1.000000  0.399298  1.000000 -0.969248
x2  0.399298  1.000000  0.399298 -0.472866
x3  1.000000  0.399298  1.000000 -0.969248
x4 -0.969248 -0.472866 -0.969248  1.000000

Top Absolute Correlations
x1  x3    1.000000
x3  x4    0.969248
x1  x4    0.969248
dtype: float64

3
замість get_redundant_pairs (df), ви можете використовувати "cor.loc [:,:] = np.tril (cor.values, k = -1)", а потім "cor = cor [cor> 0]"
Сара

2
Я отримую помилку для рядка au_corr = au_corr.drop(labels=labels_to_drop).sort_values(ascending=False):# -- partial selection or non-unique index
stallingOne

40

Рішення кількох рядків без зайвих пар змінних:

corr_matrix = df.corr().abs()

#the matrix is symmetric so we need to extract upper triangle matrix without diagonal (k = 1)

sol = (corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k=1).astype(np.bool))
                  .stack()
                  .sort_values(ascending=False))

#first element of sol series is the pair with the biggest correlation

Потім ви можете переглядати імена пар змінних (які є пандами. Серія мультиіндексів) та їх значення, як це:

for index, value in sol.items():
  # do some staff

3
можливо, погана ідея використовувати osяк ім'я змінної, оскільки воно маскує osвід, import osякщо воно доступне в коді
shadi

Дякую за вашу пропозицію, я змінив цю неналежну назву var.
MiFi

1
станом на 2018 рік замість замовлення
Serafins

1
як цикл "sol" ??
sirjay

2
@sirjay Я дав відповідь на ваше запитання вище
MiFi

13

Поєднуючи деякі функції відповідей @HYRY та @ arun, ви можете надрукувати основні кореляції для фрейму даних dfв один рядок, використовуючи:

df.corr().unstack().sort_values().drop_duplicates()

Примітка: мінус - якщо у вас є 1,0 кореляції, які не є однією змінною для себе, drop_duplicates()додавання їх видалить


1
Чи не drop_duplicatesскинуть усі рівні кореляції?
Шаді,

@shadi так, ти маєш рацію. Однак ми припускаємо, що єдиними кореляціями, які будуть однаково рівними, є кореляції 1,0 (тобто змінна сама з собою). Швидше за все, кореляція для двох унікальних пар змінних (тобто v1до v2і v3до v4) не була б абсолютно однаковою
Аддісон Клінке

Безумовно, мій фаворит, сама простота. у своєму використанні я спершу фільтрував високі суперечки
Джеймс

9

Використовуйте наведений нижче код, щоб переглянути кореляції в порядку зменшення.

# See the correlations in descending order

corr = df.corr() # df is the pandas dataframe
c1 = corr.abs().unstack()
c1.sort_values(ascending = False)

1
Ваш 2-й рядок повинен бути: c1 = core.abs (). Unstack ()
Джек Флієтінг

або перший рядокcorr = df.corr()
vizyourdata

4

Ви можете зробити графічно відповідно до цього простого коду, замінивши свої дані.

corr = df.corr()

kot = corr[corr>=.9]
plt.figure(figsize=(12,8))
sns.heatmap(kot, cmap="Greens")

введіть тут опис зображення


2

Тут є багато хороших відповідей. Найпростіший спосіб, який я знайшов, - це поєднання деяких відповідей вище.

corr = corr.where(np.triu(np.ones(corr.shape), k=1).astype(np.bool))
corr = corr.unstack().transpose()\
    .sort_values(by='column', ascending=False)\
    .dropna()

2

Використовуйте itertools.combinationsдля отримання всіх унікальних кореляцій із власної матриці кореляції панд, .corr()генеруйте список списків і подавайте його назад у DataFrame, щоб використовувати '.sort_values'. Встановити ascending = Trueдля відображення найнижчих кореляцій зверху

corrankприймає DataFrame як аргумент, оскільки він вимагає .corr().

  def corrank(X: pandas.DataFrame):
        import itertools
        df = pd.DataFrame([[(i,j),X.corr().loc[i,j]] for i,j in list(itertools.combinations(X.corr(), 2))],columns=['pairs','corr'])    
        print(df.sort_values(by='corr',ascending=False))

  corrank(X) # prints a descending list of correlation pair (Max on top)

3
Хоча цей фрагмент коду може бути рішенням, включаючи пояснення, він дійсно допомагає поліпшити якість вашої публікації. Пам’ятайте, що ви будете відповідати на запитання для читачів у майбутньому, і ці люди можуть не знати причин вашої пропозиції коду.
haindl

1

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

Тож я отримав таке спрощене рішення:

# map features to their absolute correlation values
corr = features.corr().abs()

# set equality (self correlation) as zero
corr[corr == 1] = 0

# of each feature, find the max correlation
# and sort the resulting array in ascending order
corr_cols = corr.max().sort_values(ascending=False)

# display the highly correlated features
display(corr_cols[corr_cols > 0.8])

У цьому випадку, якщо ви хочете скинути корельовані об’єкти, ви можете здійснити картографування через відфільтрований corr_colsмасив і видалити непарне (або парне).


Це просто дає один індекс (функцію), а не щось на зразок feature1 feature2 0.98. Поміняти рядок corr_cols = corr.max().sort_values(ascending=False)на corr_cols = corr.unstack()
aunsid

Ну OP не вказав форму кореляції. Як я вже згадував, я не хотів розкладати, тому я просто застосував інший підхід. Кожна пара кореляцій представлена ​​двома рядками в моєму запропонованому коді. Але дякую за корисний коментар!
falsarella

0

Я пробував деякі рішення тут, але тоді я насправді придумав своє. Сподіваюся, це може бути корисним для наступного, тому я ділюсь тут:

def sort_correlation_matrix(correlation_matrix):
    cor = correlation_matrix.abs()
    top_col = cor[cor.columns[0]][1:]
    top_col = top_col.sort_values(ascending=False)
    ordered_columns = [cor.columns[0]] + top_col.index.tolist()
    return correlation_matrix[ordered_columns].reindex(ordered_columns)

0

Це вдосконалений код від @MiFi. Це один порядок в абс, але не виключаючи негативні значення.

   def top_correlation (df,n):
    corr_matrix = df.corr()
    correlation = (corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k=1).astype(np.bool))
                 .stack()
                 .sort_values(ascending=False))
    correlation = pd.DataFrame(correlation).reset_index()
    correlation.columns=["Variable_1","Variable_2","Correlacion"]
    correlation = correlation.reindex(correlation.Correlacion.abs().sort_values(ascending=False).index).reset_index().drop(["index"],axis=1)
    return correlation.head(n)

top_correlation(ANYDATA,10)

0

Наступна функція повинна зробити трюк. Це здійснення

  • Видаляє самокореляції
  • Видаляє дублікати
  • Уможливлює вибір найкращих N найбільш корельованих функцій

і його також можна налаштувати, щоб ви могли зберігати як власні кореляції, так і дублікати. Ви також можете повідомити скільки завгодно пар функцій.


def get_feature_correlation(df, top_n=None, corr_method='spearman',
                            remove_duplicates=True, remove_self_correlations=True):
    """
    Compute the feature correlation and sort feature pairs based on their correlation

    :param df: The dataframe with the predictor variables
    :type df: pandas.core.frame.DataFrame
    :param top_n: Top N feature pairs to be reported (if None, all of the pairs will be returned)
    :param corr_method: Correlation compuation method
    :type corr_method: str
    :param remove_duplicates: Indicates whether duplicate features must be removed
    :type remove_duplicates: bool
    :param remove_self_correlations: Indicates whether self correlations will be removed
    :type remove_self_correlations: bool

    :return: pandas.core.frame.DataFrame
    """
    corr_matrix_abs = df.corr(method=corr_method).abs()
    corr_matrix_abs_us = corr_matrix_abs.unstack()
    sorted_correlated_features = corr_matrix_abs_us \
        .sort_values(kind="quicksort", ascending=False) \
        .reset_index()

    # Remove comparisons of the same feature
    if remove_self_correlations:
        sorted_correlated_features = sorted_correlated_features[
            (sorted_correlated_features.level_0 != sorted_correlated_features.level_1)
        ]

    # Remove duplicates
    if remove_duplicates:
        sorted_correlated_features = sorted_correlated_features.iloc[:-2:2]

    # Create meaningful names for the columns
    sorted_correlated_features.columns = ['Feature 1', 'Feature 2', 'Correlation (abs)']

    if top_n:
        return sorted_correlated_features[:top_n]

    return sorted_correlated_features


0

Мені найбільше сподобався пост Аддісона Клінке, як найпростіший, але я використав пропозицію Войцеха Мощинська для фільтрації та складання діаграм, але розширив фільтр, щоб уникнути абсолютних значень, тому, отримавши велику кореляційну матрицю, відфільтруй, сформулюй, а потім вирівняй:

Створено, відфільтровано та складено схему

dfCorr = df.corr()
filteredDf = dfCorr[((dfCorr >= .5) | (dfCorr <= -.5)) & (dfCorr !=1.000)]
plt.figure(figsize=(30,10))
sn.heatmap(filteredDf, annot=True, cmap="Reds")
plt.show()

карта відфільтрованого тепла

Функція

Врешті-решт, я створив невелику функцію, щоб створити кореляційну матрицю, відфільтрувати її, а потім згладити. Як ідея, її можна легко розширити, наприклад, асиметричні верхні та нижні межі тощо.

def corrFilter(x: pd.DataFrame, bound: float):
    xCorr = x.corr()
    xFiltered = xCorr[((xCorr >= bound) | (xCorr <= -bound)) & (xCorr !=1.000)]
    xFlattened = xFiltered.unstack().sort_values().drop_duplicates()
    return xFlattened

corrFilter(df, .7)

введіть тут опис зображення


як видалити найостанніший? HofstederPowerDx та Hofsteder PowerDx - це однакові змінні, так?
Люк,

можна використовувати .dropna () у функціях. Я просто спробував це у VS Code, і воно працює, де я використовую перше рівняння для створення та фільтрування матриці кореляції, а інше - для його вирівнювання. Якщо ви використовуєте це, можливо, ви захочете експериментувати з видаленням .dropduplicates (), щоб побачити, чи потрібні вам як .dropna (), так і dropduplicates ().
Джеймс Айго,

Блокнот, що містить цей код та деякі інші вдосконалення, знаходиться тут: github.com/JamesIgoe/GoogleFitAnalysis
James Igoe,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.