ใช้. cor เพื่อรับความสัมพันธ์ระหว่างสองคอลัมน์


127

ฉันมีดาต้าเฟรมแพนด้าต่อไปนี้Top15: ใส่คำอธิบายภาพที่นี่

ฉันสร้างคอลัมน์ที่ประมาณจำนวนเอกสารอ้างอิงต่อคน:

Top15['PopEst'] = Top15['Energy Supply'] / Top15['Energy Supply per Capita']
Top15['Citable docs per Capita'] = Top15['Citable documents'] / Top15['PopEst']

ฉันต้องการทราบความสัมพันธ์ระหว่างจำนวนเอกสารอ้างอิงต่อหัวกับปริมาณพลังงานต่อหัว ดังนั้นฉันจึงใช้.corr()วิธี (สหสัมพันธ์ของเพียร์สัน):

data = Top15[['Citable docs per Capita','Energy Supply per Capita']]
correlation = data.corr(method='pearson')

ฉันต้องการส่งคืนหมายเลขเดียว แต่ผลลัพธ์คือ: ใส่คำอธิบายภาพที่นี่


ฉันคิดว่าคุณถูก. แต่คุณบอกได้ไหมว่าทำไม 'data.corr (method =' pearson ')' จึงส่งคืนความสัมพันธ์ระหว่าง Energy Supply และ Energy Suppy เท่านั้น
tong zhu

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

1
โปรดพิจารณายอมรับคำตอบหากคุณคิดว่าคำตอบนั้นตอบคำถามของคุณแล้ว
MaxU

1
ฉันยอมรับคำตอบของคุณแล้วขอบคุณ
tong zhu

29
คำถามนี้ตรงจากหลักสูตร "Introduction to Data Science in Python" ใน Coursera โดยเฉพาะอย่างยิ่งการมอบหมายงาน 3 คำถามที่ 9 เมื่อผู้สอน Chris Brooks กระตุ้นให้นักเรียนโพสต์คำถามไปยัง Stack Overflow ฉันไม่คิดว่าเขาหมายความว่าพวกเขาควรโพสต์ปัญหาจากการมอบหมายคำต่อคำ
LS

คำตอบ:


210

หากไม่มีข้อมูลจริงก็ยากที่จะตอบคำถาม แต่ฉันเดาว่าคุณกำลังมองหาสิ่งนี้:

Top15['Citable docs per Capita'].corr(Top15['Energy Supply per Capita'])

ที่คำนวณความสัมพันธ์ระหว่างสองคอลัมน์ของคุณ และ'Citable docs per Capita''Energy Supply per Capita'

เพื่อเป็นตัวอย่าง:

import pandas as pd

df = pd.DataFrame({'A': range(4), 'B': [2*i for i in range(4)]})

   A  B
0  0  0
1  1  2
2  2  4
3  3  6

แล้วก็

df['A'].corr(df['B'])

ให้1ตามที่คาดไว้

ทีนี้ถ้าคุณเปลี่ยนค่าเช่น

df.loc[2, 'B'] = 4.5

   A    B
0  0  0.0
1  1  2.0
2  2  4.5
3  3  6.0

คำสั่ง

df['A'].corr(df['B'])

ผลตอบแทน

0.99586

ซึ่งยังคงใกล้เคียงกับ 1 ตามที่คาดไว้

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

df.corr()

จึงจะกลับมา

          A         B
A  1.000000  0.995862
B  0.995862  1.000000

ในกราฟิกที่คุณแสดงจะแสดงเฉพาะมุมบนซ้ายของเมทริกซ์สหสัมพันธ์เท่านั้น (ฉันถือว่า)

อาจมีบางกรณีที่คุณได้รับNaNในการแก้ปัญหาของคุณ - ตรวจสอบโพสต์นี้เพื่อดูตัวอย่าง

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


สามารถนำไปใช้ทีละแถวได้ไหม
Dr.DOOM

1
@ ดร. DOOM: ใช่มันต้องใช้ซีรีส์ดังนั้นเช่นdf.loc[1, :].corr(df.loc[2, :])จะทำงานได้ดีเช่นกัน สำหรับดาต้าเฟรมทั้งหมดคุณสามารถเปลี่ยน: df.T.corr().
Cleb

ฉันลองคำแนะนำของคุณแล้ว แต่การคำนวณยังคงส่งกลับ 1 แม้ว่าจะเปลี่ยนค่าในคอลัมน์ B โดยใช้ df.loc [2, 'B'] = 4.5 บางทีฉันอาจจะสับสนกับการคำนวณ
Dr.DOOM

@ Dr.DOOM: ยากที่จะช่วยเพราะฉันไม่รู้รหัสของคุณ ฉันเข้าใจถูกต้องหรือไม่ว่าตัวอย่างของฉันจากด้านบนส่งคืน1ในกรณีของคุณแทนที่จะเป็น 0.99586?
Cleb

1
@Cleb: ในบริบทที่ฉันทำงานดัชนีหลายคอลัมน์ระดับที่สูงกว่าทุกตัวจะมีเลเยอร์ย่อยที่เหมือนกัน ดูคำถามนี้สำหรับสิ่งที่ฉันพยายามทำ: stackoverflow.com/questions/57513002/…
Adrian Keister

7

ฉันพบปัญหาเดียวกัน มันดูเหมือนCitable Documents per Personลอยและ python ก็ข้ามมันไปโดยปริยาย คอลัมน์อื่น ๆ ทั้งหมดของ dataframe ของฉันอยู่ในรูปแบบ numpy ดังนั้นฉันจึงแก้ไขโดยการแปลง columnt เป็นnp.float64

Top15['Citable Documents per Person']=np.float64(Top15['Citable Documents per Person'])

จำไว้ว่าเป็นคอลัมน์ที่คุณคำนวณเอง


6

วิธีแก้ปัญหาของฉันคือหลังจากแปลงข้อมูลเป็นประเภทตัวเลข:

Top15[['Citable docs per Capita','Energy Supply per Capita']].corr()

การเลือกคอลัมน์จากนั้นใช้เมธอด. crr () เป็นตัวเลือกที่ดีเนื่องจากเราสามารถคำนวณความสัมพันธ์แบบคู่ระหว่างคอลัมน์มากกว่า 2 คอลัมน์
Sébastien Wieckowski

4

หากคุณต้องการความสัมพันธ์ระหว่างคู่ของคอลัมน์ทั้งหมดคุณสามารถทำสิ่งนี้:

import pandas as pd
import numpy as np

def get_corrs(df):
    col_correlations = df.corr()
    col_correlations.loc[:, :] = np.tril(col_correlations, k=-1)
    cor_pairs = col_correlations.stack()
    return cor_pairs.to_dict()

my_corrs = get_corrs(df)
# and the following line to retrieve the single correlation
print(my_corrs[('Citable docs per Capita','Energy Supply per Capita')])

3

เมื่อคุณเรียกสิ่งนี้:

data = Top15[['Citable docs per Capita','Energy Supply per Capita']]
correlation = data.corr(method='pearson')

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

ทำการเชื่อมโยงระหว่างสองชุดเพื่อให้ได้ค่าเดียว:

from scipy.stats.stats import pearsonr
docs_col = Top15['Citable docs per Capita'].values
energy_col = Top15['Energy Supply per Capita'].values
corr , _ = pearsonr(docs_col, energy_col)

หรือถ้าคุณต้องการค่าเดียวจากฟังก์ชันเดียวกัน (DataFrame's corr):

single_value = correlation[0][1] 

หวังว่านี่จะช่วยได้


3

การทำงานเช่นนี้:

Top15['Citable docs per Capita']=np.float64(Top15['Citable docs per Capita'])

Top15['Energy Supply per Capita']=np.float64(Top15['Energy Supply per Capita'])

Top15['Energy Supply per Capita'].corr(Top15['Citable docs per Capita'])

1

ฉันแก้ไขปัญหานี้โดยการเปลี่ยนประเภทข้อมูล หากคุณเห็น 'Energy Supply per Capita' เป็นประเภทตัวเลขในขณะที่ 'Citable docs per Capita' เป็นประเภทออบเจ็กต์ ฉันแปลงคอลัมน์ให้ลอยโดยใช้ astype ฉันมีปัญหาเดียวกันกับฟังก์ชั่น np บางอย่าง: count_nonzeroและsumทำงานได้ในขณะที่meanและstdไม่ทำ


0

การเปลี่ยน 'Citable docs per Capita' เป็นตัวเลขก่อนที่ความสัมพันธ์จะแก้ปัญหาได้

    Top15['Citable docs per Capita'] = pd.to_numeric(Top15['Citable docs per Capita'])
    data = Top15[['Citable docs per Capita','Energy Supply per Capita']]
    correlation = data.corr(method='pearson')
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.