แสดงรายการคู่ความสัมพันธ์สูงสุดจากเมทริกซ์สหสัมพันธ์ขนาดใหญ่ในหมีแพนด้า?


97

คุณพบความสัมพันธ์อันดับต้น ๆ ในเมทริกซ์สหสัมพันธ์กับหมีแพนด้าได้อย่างไร? มีคำตอบมากมายเกี่ยวกับวิธีการทำสิ่งนี้กับ R ( แสดงความสัมพันธ์เป็นรายการสั่งซื้อไม่ใช่เมทริกซ์ขนาดใหญ่หรือวิธีที่มีประสิทธิภาพในการรับคู่ที่มีความสัมพันธ์กันสูงจากชุดข้อมูลขนาดใหญ่ใน Python หรือ R ) แต่ฉันสงสัยว่าจะทำอย่างไร กับแพนด้า? ในกรณีของฉันเมทริกซ์คือ 4460x4460 ดังนั้นจึงไม่สามารถมองเห็นได้

คำตอบ:


93

คุณสามารถใช้DataFrame.valuesเพื่อรับอาร์เรย์ของข้อมูลจากนั้นใช้ฟังก์ชัน 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 และสูงกว่าคุณควรใช้ sort_values ​​แทนลำดับ คุณจะได้รับข้อผิดพลาดหากคุณลองใช้วิธีการสั่งซื้อ
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]"
Sarah

2
ฉันได้รับความผิดพลาดสำหรับ line au_corr = au_corr.drop(labels=labels_to_drop).sort_values(ascending=False):# -- partial selection or non-unique index
stallingOne

41

โซลูชันไม่กี่บรรทัดที่ไม่มีคู่ตัวแปรซ้ำซ้อน:

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ถ้ามีอยู่ในโค้ด
เฉดสี

ขอบคุณสำหรับคำแนะนำฉันเปลี่ยนชื่อตัวแปรที่ไม่เหมาะสมนี้
MiFi

1
ในปี 2018 ให้ใช้sort_values ​​(จากน้อยไปมาก = False)แทนลำดับ
Serafins

1
วน 'โซล' ยังไง ??
sirjay

2
@sirjay ฉันตอบคำถามของคุณไว้ข้างบน
MiFi

13

เมื่อรวมคุณสมบัติบางอย่างของคำตอบของ @HYRY และ @ arun คุณสามารถพิมพ์ความสัมพันธ์ระดับบนสุดสำหรับ dataframe dfในบรรทัดเดียวโดยใช้:

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

หมายเหตุ: ข้อเสียอย่างหนึ่งคือถ้าคุณมี 1.0 สหสัมพันธ์ที่ไม่ใช่ตัวแปรเดียวการdrop_duplicates()เพิ่มจะลบออก


1
จะไม่drop_duplicatesทิ้งความสัมพันธ์ทั้งหมดที่เท่ากันหรือ?
shai

@shadi ใช่คุณถูกต้อง อย่างไรก็ตามเราถือว่าความสัมพันธ์เดียวที่จะเท่ากันคือสหสัมพันธ์ของ 1.0 (นั่นคือตัวแปรกับตัวมันเอง) โอกาสที่ความสัมพันธ์ของตัวแปรสองคู่ที่ไม่ซ้ำกัน (เช่นv1ถึงv2และv3ถึงv4) จะไม่เหมือนกันทุก
ประการ

แน่นอนสิ่งที่ฉันชอบคือความเรียบง่าย ในการใช้งานของฉันฉันกรองก่อนเพื่อให้มี corrleations สูง
James Igoe

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

หรือบรรทัดแรก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 ไม่ได้ระบุรูปร่างความสัมพันธ์ ดังที่ฉันได้กล่าวไปแล้วฉันไม่ต้องการที่จะปลดล็อกดังนั้นฉันจึงนำวิธีการอื่น คู่ความสัมพันธ์แต่ละคู่แสดงด้วย 2 แถวในรหัสที่ฉันแนะนำ แต่ขอบคุณสำหรับความคิดเห็นที่เป็นประโยชน์!
falsarella

1

ฉันชอบโพสต์ของ Addison Klinke มากที่สุดเนื่องจากเป็นวิธีที่ง่ายที่สุด แต่ใช้คำแนะนำของ Wojciech Moszczyńskในการกรองและสร้างแผนภูมิ แต่ขยายตัวกรองเพื่อหลีกเลี่ยงค่าสัมบูรณ์ดังนั้นให้เมทริกซ์สหสัมพันธ์ขนาดใหญ่กรองแผนภูมิแล้วทำให้แบน:

สร้างกรองและจัดทำแผนภูมิ

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 () หรือไม่
James Igoe

สมุดบันทึกที่มีรหัสนี้และการปรับปรุงอื่น ๆ อยู่ที่นี่: github.com/JamesIgoe/GoogleFitAnalysis
James Igoe

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 คำสั่งนี้เป็น abs แต่ไม่รวมค่าลบ

   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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.