Verwenden Sie .corr, um die Korrelation zwischen zwei Spalten zu ermitteln

126

Ich habe den folgenden Pandas-Datenrahmen Top15: Geben Sie hier die Bildbeschreibung ein

Ich erstelle eine Spalte, in der die Anzahl der zitierfähigen Dokumente pro Person geschätzt wird:

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

Ich möchte den Zusammenhang zwischen der Anzahl zitierfähiger Dokumente pro Kopf und der Energieversorgung pro Kopf kennen. Also benutze ich die .corr()Methode (Pearson-Korrelation):

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

Ich möchte eine einzelne Nummer zurückgeben, aber das Ergebnis ist: Geben Sie hier die Bildbeschreibung ein

tong zhu
quelle
Ich glaube, Du hast recht. Aber können Sie mir sagen, warum die 'data.corr (method =' pearson ')' nur die Beziehung zwischen Energieversorgung und Energieversorgung zurückgibt?
Tong Zhu
1
Es tut nicht. Es sollte Ihnen eine 2x2-Matrix zurückgeben. Sie zeigen den oberen linken Eintrag. Wenn Sie .corrdirekt auf Ihren Datenrahmen anwenden, werden alle paarweisen Korrelationen zurückgegeben. Deshalb beobachten Sie dann 1s in der Diagonale Ihrer Matrix (jede Spalte ist perfekt mit sich selbst korreliert). Siehe meine Bearbeitung unten.
Cleb
1
Bitte erwägen Sie , eine Antwort zu akzeptieren , wenn Sie der Meinung sind, dass sie Ihre Frage beantwortet hat
MaxU
1
Ich habe Ihre Antwort angenommen, danke
tong zhu
28
Diese Frage stammt direkt aus dem Kurs "Einführung in Data Science in Python" zu Coursera. Insbesondere Aufgabe 3, Frage 9. Wenn Ausbilder Chris Brooks die Schüler dazu ermutigt, Fragen an Stack Overflow zu senden, meinte er nicht, dass sie Probleme aus den Aufgaben wörtlich veröffentlichen sollten.
LS

Antworten:

207

Ohne tatsächliche Daten ist es schwierig, die Frage zu beantworten, aber ich denke, Sie suchen nach so etwas:

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

Das berechnet die Korrelation zwischen Ihren beiden Spalten 'Citable docs per Capita' und 'Energy Supply per Capita'.

Um ein Beispiel zu geben:

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

Dann

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

gibt 1wie erwartet.

Wenn Sie nun einen Wert ändern, z

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

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

der Befehl

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

kehrt zurück

0.99586

das ist immer noch nahe an 1, wie erwartet.

Wenn Sie .corrdirekt auf Ihren Datenrahmen anwenden, werden alle paarweisen Korrelationen zwischen Ihren Spalten zurückgegeben . Deshalb beobachten Sie dann 1san der Diagonale Ihrer Matrix (jede Spalte ist perfekt mit sich selbst korreliert).

df.corr()

werde daher zurückkehren

          A         B
A  1.000000  0.995862
B  0.995862  1.000000

In der Grafik, die Sie zeigen, wird nur die obere linke Ecke der Korrelationsmatrix dargestellt (nehme ich an).

Es kann Fälle geben, in denen Sie NaNs in Ihrer Lösung erhalten - überprüfen Sie diesen Beitrag für ein Beispiel.

Wenn Sie Einträge über / unter einem bestimmten Schwellenwert filtern möchten, können Sie diese Frage überprüfen . Wenn Sie eine Heatmap der Korrelationskoeffizienten zeichnen möchten, können Sie diese Antwort überprüfen. Wenn Sie dann auf das Problem mit überlappenden Achsenbeschriftungen stoßen, lesen Sie den folgenden Beitrag .

Cleb
quelle
Kann dies zeilenweise angewendet werden?
Dr.DOOM
1
@ Dr.DOOM: Ja, es dauert nur Serien, also wird zB df.loc[1, :].corr(df.loc[2, :])auch gut funktionieren. Für den gesamten Datenrahmen können Sie einfach transponieren : df.T.corr().
Cleb
Ich habe Ihren Vorschlag ausprobiert, aber die Berechnung gibt immer noch 1 zurück, selbst nachdem der a-Wert in Spalte B mit df.loc [2, 'B'] = 4.5 geändert wurde. Vielleicht
bin ich
@ Dr.DOOM: Schwer zu helfen, da ich Ihren Code nicht kenne. Habe ich richtig verstanden, dass mein Beispiel von oben 1in Ihrem Fall statt zurückkehrt 0.99586?
Cleb
1
@Cleb: Nun, in dem Kontext, in dem ich arbeite, hat jeder übergeordnete mehrspaltige Index identische Unterschichten. Sehen Sie diese Frage für das, was ich versuche zu tun: stackoverflow.com/questions/57513002/…
Adrian Keister
7

Ich bin auf das gleiche Problem gestoßen. Es schien Citable Documents per Personein Float zu sein, und Python überspringt es standardmäßig irgendwie. Alle anderen Spalten meines Datenrahmens hatten Numpy-Formate, daher habe ich das Problem gelöst, indem ich die Spalte in konvertiert habenp.float64

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

Denken Sie daran, dass es genau die Spalte ist, die Sie selbst berechnet haben

Gary
quelle
6

Meine Lösung wäre nach der Konvertierung von Daten in einen numerischen Typ:

Top15[['Citable docs per Capita','Energy Supply per Capita']].corr()
ibozkurt79
quelle
Das Auswählen von Spalten und das anschließende Anwenden der .corr () -Methode ist eine gute Option, da wir die Korrelation paarweise zwischen mehr als 2 Spalten berechnen können
Sébastien Wieckowski
4

Wenn Sie die Korrelationen zwischen allen Spaltenpaaren möchten, können Sie Folgendes tun:

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')])
mgoldwasser
quelle
3

Wenn Sie dies nennen:

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

Da die Funktion DataFrame.corr () paarweise Korrelationen ausführt, haben Sie vier Paare aus zwei Variablen. Im Grunde genommen erhalten Sie diagonale Werte als Autokorrelation (Korrelation mit sich selbst, zwei Werte, da Sie zwei Variablen haben) und zwei andere Werte als Kreuzkorrelationen zwischen einer und einer anderen und umgekehrt.

Führen Sie entweder eine Korrelation zwischen zwei Reihen durch, um einen einzelnen Wert zu erhalten:

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)

oder, wenn Sie einen einzelnen Wert aus derselben Funktion (DataFrame's corr) möchten:

single_value = correlation[0][1] 

Hoffe das hilft.

aumpen
quelle
3

Es funktioniert so:

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'])
Orca
quelle
1

Ich habe dieses Problem durch Ändern des Datentyps gelöst. Wenn Sie sehen, dass die 'Energieversorgung pro Kopf' ein numerischer Typ ist, während die 'Zitierbare Dokumente pro Kopf' ein Objekttyp ist. Ich habe die Spalte mit astype in float konvertiert. Ich hatte das gleiche Problem mit einigen np-Funktionen: count_nonzeround sumarbeitete während meanund stdnicht.

BIETEN
quelle
0

Wenn Sie "Citable Docs per Capita" vor der Korrelation in "numerisch" ändern, wird das Problem behoben.

    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')
Moinul Hossain
quelle