Buat daftar Pasangan Korelasi Tertinggi dari Matriks Korelasi Besar di Panda?


97

Bagaimana Anda menemukan korelasi teratas dalam matriks korelasi dengan Pandas? Ada banyak jawaban tentang bagaimana melakukan ini dengan R ( Tunjukkan korelasi sebagai daftar berurutan, bukan sebagai matriks besar atau cara Efisien untuk mendapatkan pasangan berkorelasi tinggi dari kumpulan data besar dengan Python atau R ), tetapi saya bertanya-tanya bagaimana melakukannya dengan panda? Dalam kasus saya, matriksnya adalah 4460x4460, jadi tidak dapat melakukannya secara visual.

Jawaban:


93

Anda dapat menggunakan DataFrame.valuesuntuk mendapatkan larik data yang numpy dan kemudian menggunakan fungsi NumPy seperti argsort()untuk mendapatkan pasangan yang paling berkorelasi.

Tetapi jika Anda ingin melakukan ini di panda, Anda dapat unstackdan mengurutkan 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]

Ini hasilnya:

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
Dengan Pandas v 0.17.0 dan yang lebih tinggi, Anda harus menggunakan sort_values, bukan urutan. Anda akan mendapatkan pesan kesalahan jika mencoba menggunakan metode pemesanan.
Friendm1

46

@ HYRY Jawabannya sempurna. Hanya membangun jawaban itu dengan menambahkan sedikit lebih banyak logika untuk menghindari duplikasi dan korelasi diri serta penyortiran yang tepat:

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))

Itu memberikan hasil sebagai berikut:

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
daripada get_redundant_pairs (df), Anda dapat menggunakan "cor.loc [:,:] = np.tril (cor.values, k = -1)" dan kemudian "cor = cor [cor> 0]"
Sarah

2
Saya mendapatkan kesalahan untuk baris au_corr = au_corr.drop(labels=labels_to_drop).sort_values(ascending=False):# -- partial selection or non-unique index
stallingOne

41

Solusi beberapa baris tanpa pasangan variabel yang berlebihan:

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

Kemudian Anda dapat melakukan iterasi melalui nama pasangan variabel (yaitu pandas.Series multi-indexes) dan nilainya seperti ini:

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

3
mungkin ide yang buruk untuk digunakan ossebagai nama variabel karena menutupi osdari import osjika tersedia dalam kode
shadi

Terima kasih atas saran Anda, saya mengubah nama var yang tidak benar ini.
MiFi

1
pada 2018 gunakan sort_values ​​(ascending = False) alih-alih urutan
Serafins

1
bagaimana cara mengulang 'sol' ??
sirjay

2
@sirjay Saya memberikan jawaban untuk pertanyaan Anda di atas
MiFi

13

Menggabungkan beberapa fitur jawaban @HYRY dan @ arun, Anda dapat mencetak korelasi teratas untuk kerangka data dfdalam satu baris menggunakan:

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

Catatan: satu sisi negatifnya adalah jika Anda memiliki korelasi 1.0 yang bukan merupakan satu variabel, drop_duplicates()penambahan akan menghapusnya


1
Tidakkah akan drop_duplicatesmenghilangkan semua korelasi yang sama?
shadi

@shadi ya, kamu benar. Namun, kami mengasumsikan satu-satunya korelasi yang akan identik sama adalah korelasi 1,0 (yaitu variabel dengan dirinya sendiri). Kemungkinannya adalah bahwa korelasi untuk dua pasang variabel unik (yaitu v1ke v2dan v3ke v4) tidak akan persis sama
Addison Klinke

Pasti favorit saya, kesederhanaan itu sendiri. dalam penggunaan saya, saya memfilter terlebih dahulu untuk koreksi tinggi
James Igoe

9

Gunakan kode di bawah ini untuk melihat korelasi dalam urutan menurun.

# See the correlations in descending order

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

1
Baris ke-2 Anda harus: c1 = core.abs (). Unstack ()
Jack Fleeting

atau baris pertamacorr = df.corr()
vizyourdata

4

Anda dapat melakukan secara grafis menurut kode sederhana ini dengan mengganti data Anda.

corr = df.corr()

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

masukkan deskripsi gambar di sini


2

Banyak jawaban bagus di sini. Cara termudah yang saya temukan adalah kombinasi dari beberapa jawaban di atas.

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

Gunakan itertools.combinationsuntuk mendapatkan semua korelasi unik dari matriks korelasi panda itu sendiri .corr(), buat daftar daftar dan masukkan kembali ke DataFrame untuk menggunakan '.sort_values'. Atur ascending = Trueuntuk menampilkan korelasi terendah di atas

corrankmengambil DataFrame sebagai argumen karena membutuhkan .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
Meskipun cuplikan kode ini mungkin bisa menjadi solusinya, menyertakan penjelasan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa mendatang, dan orang-orang itu mungkin tidak tahu alasan saran kode Anda.
haindl

1

Saya tidak ingin unstackatau memperumit masalah ini, karena saya hanya ingin melepaskan beberapa fitur yang sangat berkorelasi sebagai bagian dari fase pemilihan fitur.

Jadi saya berakhir dengan solusi sederhana berikut:

# 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])

Dalam kasus ini, jika Anda ingin corr_colsmenghilangkan fitur yang berkorelasi, Anda dapat memetakan melalui array yang difilter dan menghapus yang diindeks ganjil (atau bahkan diindeks).


Ini hanya memberikan satu indeks (fitur) dan bukan sesuatu seperti feature1 feature2 0,98. Ganti baris corr_cols = corr.max().sort_values(ascending=False)ke corr_cols = corr.unstack()
aunsid

Nah, OP tidak menentukan bentuk korelasi. Seperti yang saya sebutkan, saya tidak ingin melepaskannya, jadi saya hanya membawa pendekatan yang berbeda. Setiap pasangan korelasi diwakili oleh 2 baris, dalam kode yang saya sarankan. Tapi terima kasih atas komentar yang membantu!
falsarella

1

Saya paling menyukai posting Addison Klinke, sebagai yang paling sederhana, tetapi menggunakan saran Wojciech Moszczyńsk untuk pemfilteran dan pembuatan bagan, tetapi memperluas filter untuk menghindari nilai absolut, jadi berikan matriks korelasi yang besar, filter, bagan, dan kemudian ratakan:

Dibuat, Difilter, dan Dipetakan

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()

peta panas yang disaring

Fungsi

Pada akhirnya, saya membuat fungsi kecil untuk membuat matriks korelasi, memfilternya, dan kemudian meratakannya. Sebagai gagasan, itu dapat dengan mudah diperpanjang, misalnya, batas atas dan bawah yang asimetris, dll.

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)

masukkan deskripsi gambar di sini


bagaimana cara menghapus yang terakhir? HofstederPowerDx dan Hofsteder PowerDx adalah variabel yang sama, bukan?
Luc

seseorang dapat menggunakan .dropna () dalam fungsi. Saya baru saja mencobanya di VS Code dan berhasil, di mana saya menggunakan persamaan pertama untuk membuat dan memfilter matriks korelasi, dan persamaan lainnya untuk meratakannya. Jika Anda menggunakannya, Anda mungkin ingin bereksperimen dengan menghapus .dropduplicates () untuk melihat apakah Anda memerlukan .dropna () dan dropduplicates ().
James Igoe

Notebook yang menyertakan kode ini dan beberapa peningkatan lainnya ada di sini: github.com/JamesIgoe/GoogleFitAnalysis
James Igoe

0

Saya mencoba beberapa solusi di sini tetapi kemudian saya benar-benar menemukan solusi saya sendiri. Semoga bermanfaat untuk yang berikutnya jadi saya bagikan di sini:

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

Ini adalah kode perbaikan dari @MiFi. Urutan satu ini di abs tetapi tidak mengecualikan nilai negatif.

   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

Fungsi berikut harus melakukan triknya. Implementasi ini

  • Menghapus korelasi diri
  • Menghapus duplikat
  • Mengaktifkan pemilihan fitur berkorelasi tertinggi N teratas

dan juga dapat dikonfigurasi sehingga Anda dapat menyimpan baik korelasi diri maupun duplikatnya. Anda juga dapat melaporkan pasangan fitur sebanyak yang Anda inginkan.


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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.