พล็อตเมทริกซ์สหสัมพันธ์พล็อตโดยใช้แพนด้า


212

ฉันมีชุดข้อมูลที่มีคุณสมบัติจำนวนมากดังนั้นการวิเคราะห์เมทริกซ์ความสัมพันธ์จึงเป็นเรื่องยากมาก ฉันต้องการพล็อตเมทริกซ์สหสัมพันธ์ที่เราใช้dataframe.corr()ฟังก์ชั่นจากห้องสมุดแพนด้า มีฟังก์ชันในตัวที่จัดทำโดยห้องสมุดแพนด้าเพื่อพล็อตเมทริกซ์นี้หรือไม่?


คำตอบที่เกี่ยวข้องสามารถพบได้ที่นี่การสร้าง heatmap จาก pandas DataFrame
joelostblom

คำตอบ:


292

คุณสามารถใช้pyplot.matshow() จากmatplotlib:

import matplotlib.pyplot as plt

plt.matshow(dataframe.corr())
plt.show()

แก้ไข:

ในความคิดเห็นคือการร้องขอวิธีการเปลี่ยนป้ายเห็บแกน ต่อไปนี้เป็นรุ่นดีลักซ์ที่วาดบนขนาดตัวเลขที่ใหญ่กว่ามีป้ายกำกับแกนเพื่อให้ตรงกับ dataframe และ colorbar legend เพื่อตีความมาตราส่วนสี

ฉันรวมถึงวิธีการปรับขนาดและการหมุนของฉลากและฉันใช้อัตราส่วนรูปที่ทำให้แถบสีและตัวเลขหลักออกมาสูงเท่ากัน

f = plt.figure(figsize=(19, 15))
plt.matshow(df.corr(), fignum=f.number)
plt.xticks(range(df.shape[1]), df.columns, fontsize=14, rotation=45)
plt.yticks(range(df.shape[1]), df.columns, fontsize=14)
cb = plt.colorbar()
cb.ax.tick_params(labelsize=14)
plt.title('Correlation Matrix', fontsize=16);

ตัวอย่างพล็อตสหสัมพันธ์


1
ฉันต้องคิดถึงบางอย่าง:AttributeError: 'module' object has no attribute 'matshow'
Tom Russell

1
@TomRussell คุณทำimport matplotlib.pyplot as pltอะไร
joelostblom

1
ฉันอยากจะคิดว่าฉันทำ! :-)
Tom Russell

7
คุณรู้วิธีแสดงชื่อคอลัมน์จริง ๆ บนโครงหรือไม่?
WebQube

2
@ เซซิเลียฉันได้แก้ไขเรื่องนี้โดยการเปลี่ยนพารามิเตอร์การหมุนเป็น90
ikbel benabdessamad

182

หากเป้าหมายหลักของคุณคือการมองเห็นเมทริกซ์ความสัมพันธ์มากกว่าการสร้างพล็อตต่อการpandas เลือกตัวเลือกการจัดแต่งทรงผมที่สะดวกสบายเป็นโซลูชั่นในตัวที่ทำงานได้:

import pandas as pd
import numpy as np

rs = np.random.RandomState(0)
df = pd.DataFrame(rs.rand(10, 10))
corr = df.corr()
corr.style.background_gradient(cmap='coolwarm')
# 'RdBu_r' & 'BrBG' are other good diverging colormaps

ป้อนคำอธิบายรูปภาพที่นี่

โปรดทราบว่าสิ่งนี้จะต้องอยู่ในส่วนแบ็คเอนด์ที่รองรับการแสดงผล HTML เช่น JupyterLab Notebook (ข้อความแสงอัตโนมัติบนพื้นหลังสีเข้มมาจาก PR ที่มีอยู่ไม่ใช่รุ่นที่เผยแพร่ล่าสุดคือpandas0.23)


การออกแบบ

คุณสามารถจำกัดความแม่นยำหลักได้อย่างง่ายดาย:

corr.style.background_gradient(cmap='coolwarm').set_precision(2)

ป้อนคำอธิบายรูปภาพที่นี่

หรือกำจัดตัวเลขทั้งหมดหากคุณต้องการเมทริกซ์โดยไม่มีหมายเหตุประกอบ:

corr.style.background_gradient(cmap='coolwarm').set_properties(**{'font-size': '0pt'})

ป้อนคำอธิบายรูปภาพที่นี่

เอกสารการใส่สไตล์ยังมีคำแนะนำเกี่ยวกับสไตล์ขั้นสูงเช่นวิธีเปลี่ยนการแสดงของเซลล์ที่ตัวชี้เมาส์เลื่อนอยู่ หากต้องการบันทึกผลลัพธ์คุณสามารถคืนค่า HTML โดยเพิ่มrender()วิธีการต่อจากนั้นเขียนลงในไฟล์ (หรือใช้ภาพหน้าจอเพื่อจุดประสงค์ที่เป็นทางการน้อยกว่า)


เปรียบเทียบเวลา

ในการทดสอบของฉันstyle.background_gradient()มี 4x เร็วกว่าplt.matshow()และ 120x เร็วกว่าsns.heatmap()กับเมทริกซ์ 10x10 น่าเสียดายที่มันไม่ได้ปรับขนาดเช่นกันplt.matshow(): ทั้งสองใช้เวลาประมาณเดียวกันสำหรับเมทริกซ์ 100x100 และplt.matshow()เร็วขึ้น 10 เท่าสำหรับเมทริกซ์ 1000x1000


ประหยัด

มีวิธีที่เป็นไปได้สองสามวิธีในการบันทึกดาต้าเฟรมที่มีสไตล์:

  • ส่งคืน HTML โดยการผนวกrender()วิธีการแล้วเขียนผลลัพธ์ไปยังไฟล์
  • บันทึกเป็น.xslxไฟล์ที่มีการจัดรูปแบบตามเงื่อนไขโดยต่อท้ายto_excel()เมธอด
  • รวมกับ imgkit เพื่อบันทึกบิตแมป
  • ถ่ายภาพหน้าจอ (เพื่อวัตถุประสงค์ที่เป็นทางการน้อยกว่า)

อัปเดตสำหรับหมีแพนด้า> = 0.24

โดยการตั้งค่าaxis=Noneตอนนี้เป็นไปได้ที่จะคำนวณสีตามเมทริกซ์ทั้งหมดแทนที่จะเป็นต่อคอลัมน์หรือต่อแถว:

corr.style.background_gradient(cmap='coolwarm', axis=None)

ป้อนคำอธิบายรูปภาพที่นี่


2
หากมีวิธีการส่งออกเป็นภาพก็จะดี!
Kristada673

1
ขอบคุณ! คุณต้องมีจานสีที่แตกต่างกันอย่างแน่นอนimport seaborn as sns corr = df.corr() cm = sns.light_palette("green", as_cmap=True) cm = sns.diverging_palette(220, 20, sep=20, as_cmap=True) corr.style.background_gradient(cmap=cm).set_precision(2)
หยุดทำงาน

1
@stallingOne จุดที่ดีฉันไม่ควรรวมค่าลบในตัวอย่างฉันอาจเปลี่ยนค่านั้นในภายหลัง เพียงสำหรับการอ้างอิงสำหรับคนที่อ่านข้อความนี้คุณไม่จำเป็นต้องสร้างความแตกต่าง CMAP กำหนดเองด้วยทะเล (แม้ว่าหนึ่งในความคิดเห็นดังกล่าวข้างต้นมีลักษณะเนียนสวย) คุณยังสามารถใช้ในตัว CMAPs แตกต่างจาก matplotlib corr.style.background_gradient(cmap='coolwarm')เช่น ขณะนี้ยังไม่มีวิธีที่จะจัดศูนย์กลาง cmap ไว้ที่ค่าเฉพาะซึ่งเป็นความคิดที่ดีสำหรับ cmap ที่แตกต่างกัน
joelostblom

1
@rovyko คุณอยู่บน pandas> = 0.24.0 หรือไม่
joelostblom

2
แปลงเหล่านี้ยอดเยี่ยมมาก แต่คำถาม @ Kristada673 มีความเกี่ยวข้องมากคุณจะส่งออกอย่างไร
Erfan

89

ลองใช้ฟังก์ชันนี้ซึ่งแสดงชื่อตัวแปรสำหรับเมทริกซ์สหสัมพันธ์:

def plot_corr(df,size=10):
    '''Function plots a graphical correlation matrix for each pair of columns in the dataframe.

    Input:
        df: pandas DataFrame
        size: vertical and horizontal size of the plot'''

    corr = df.corr()
    fig, ax = plt.subplots(figsize=(size, size))
    ax.matshow(corr)
    plt.xticks(range(len(corr.columns)), corr.columns);
    plt.yticks(range(len(corr.columns)), corr.columns);

6
plt.xticks(range(len(corr.columns)), corr.columns, rotation='vertical')ถ้าคุณต้องการการวางแนวแนวตั้งของชื่อคอลัมน์บนแกน x
nishant

สิ่งกราฟิกอื่น แต่การเพิ่มplt.tight_layout()อาจมีประโยชน์สำหรับชื่อคอลัมน์แบบยาว
3017048

86

เวอร์ชั่นแผนที่ความร้อนของ Seaborn:

import seaborn as sns
corr = dataframe.corr()
sns.heatmap(corr, 
            xticklabels=corr.columns.values,
            yticklabels=corr.columns.values)

9
แผนที่ความร้อนของทะเลเป็นสิ่งที่แฟนซี แต่มันก็ทำงานได้ไม่ดีในเมทริกซ์ขนาดใหญ่ วิธี matshow ของ matplotlib นั้นเร็วกว่ามาก
anilbey

3
Seaborn สามารถอนุมาน ticklablabels จากชื่อคอลัมน์ได้โดยอัตโนมัติ
Tulio Casagrande

80

คุณสามารถสังเกตความสัมพันธ์ระหว่างฟีเจอร์ต่างๆได้โดยการวาดแผนที่ความร้อนจากทะเลหรือแมทริกซ์กระจายจากนุ่น

เมทริกซ์กระจาย:

pd.scatter_matrix(dataframe, alpha = 0.3, figsize = (14,8), diagonal = 'kde');

หากคุณต้องการเห็นภาพความเบ้ของแต่ละสถานที่ให้ใช้คู่ซีบรูน

sns.pairplot(dataframe)

Sns Heatmap:

import seaborn as sns

f, ax = pl.subplots(figsize=(10, 8))
corr = dataframe.corr()
sns.heatmap(corr, mask=np.zeros_like(corr, dtype=np.bool), cmap=sns.diverging_palette(220, 10, as_cmap=True),
            square=True, ax=ax)

ผลลัพธ์จะเป็นแผนที่ความสัมพันธ์ของคุณสมบัติ ie ดูตัวอย่างด้านล่าง

ป้อนคำอธิบายรูปภาพที่นี่

ความสัมพันธ์ระหว่างร้านขายของชำและผงซักฟอกอยู่ในระดับสูง ในทำนองเดียวกัน:

Pdoducts ที่มีสหสัมพันธ์สูง:
  1. ร้านขายของชำและผงซักฟอก
ผลิตภัณฑ์ที่มีสหสัมพันธ์ปานกลาง:
  1. นมและร้านขายของชำ
  2. นมและผงซักฟอก _ กระดาษ
ผลิตภัณฑ์ที่มีสหสัมพันธ์ต่ำ:
  1. นมและอาหารสำเร็จรูป
  2. แช่แข็งและสด
  3. แช่แข็งและอาหารสำเร็จรูป

จาก Pairplots: คุณสามารถสังเกตความสัมพันธ์ชุดเดียวกันจาก pairplots หรือเมทริกซ์กระจาย แต่จากสิ่งเหล่านี้เราสามารถพูดได้ว่าข้อมูลถูกกระจายตามปกติหรือไม่

ป้อนคำอธิบายรูปภาพที่นี่

หมายเหตุ: กราฟข้างต้นเป็นกราฟเดียวกันที่นำมาจากข้อมูลซึ่งใช้ในการวาดแผนที่ความร้อน


3
ฉันคิดว่ามันควรจะเป็น. plt ไม่ได้. pl (หากนี่หมายถึง matplotlib)
ghukill

2
@ghukill ไม่จำเป็น เขาอาจเรียกมันว่าfrom matplotlib import pyplot as pl
Jeru Luke

วิธีการกำหนดขอบเขตของความสัมพันธ์ระหว่าง -1 ถึง +1 เสมอในพล็อตสหสัมพันธ์
debaonline4u

7

คุณสามารถใช้วิธี imshow () จาก matplotlib

import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('ggplot')

plt.imshow(X.corr(), cmap=plt.cm.Reds, interpolation='nearest')
plt.colorbar()
tick_marks = [i for i in range(len(X.columns))]
plt.xticks(tick_marks, X.columns, rotation='vertical')
plt.yticks(tick_marks, X.columns)
plt.show()


3

กราฟิก statmodels ยังให้มุมมองที่ดีของเมทริกซ์ความสัมพันธ์

import statsmodels.api as sm
import matplotlib.pyplot as plt

corr = dataframe.corr()
sm.graphics.plot_corr(corr, xnames=list(corr.columns))
plt.show()

3

เพื่อความสมบูรณ์โซลูชันที่ง่ายที่สุดที่ฉันรู้จักกับทะเลตอนปลายปี 2562 ถ้าใครใช้Jupyter :

import seaborn as sns
sns.heatmap(dataframe.corr())

1

นอกจากวิธีการอื่นแล้วมันยังดีที่มี pairplot ซึ่งจะให้พล็อตการกระจายสำหรับทุกกรณี -

import pandas as pd
import numpy as np
import seaborn as sns
rs = np.random.RandomState(0)
df = pd.DataFrame(rs.rand(10, 10))
sns.pairplot(df)

0

เมทริกซ์สหสัมพันธ์แบบในกรณีของฉัน zdf คือดาต้าเฟรมที่ฉันต้องใช้เมทริกซ์สหสัมพันธ์

corrMatrix =zdf.corr()
corrMatrix.to_csv('sm_zscaled_correlation_matrix.csv');
html = corrMatrix.style.background_gradient(cmap='RdBu').set_precision(2).render()

# Writing the output to a html file.
with open('test.html', 'w') as f:
   print('<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-widthinitial-scale=1.0"><title>Document</title></head><style>table{word-break: break-all;}</style><body>' + html+'</body></html>', file=f)

จากนั้นเราสามารถจับภาพหน้าจอ หรือแปลง html เป็นไฟล์รูปภาพ

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