Utilisez .corr pour obtenir la corrélation entre deux colonnes

127

J'ai le dataframe pandas suivant Top15: entrez la description de l'image ici

Je crée une colonne qui estime le nombre de documents pouvant être cités par personne:

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

Je veux connaître la corrélation entre le nombre de documents citables par habitant et l'approvisionnement énergétique par habitant. J'utilise donc la .corr()méthode (corrélation de Pearson):

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

Je souhaite renvoyer un seul numéro, mais le résultat est: entrez la description de l'image ici

tong zhu
la source
Je pense que tu as raison. Mais pouvez-vous me dire pourquoi le 'data.corr (method =' pearson ')' ne renvoie que la relation entre l'approvisionnement en énergie et la demande d'énergie?
tong zhu
1
Ce ne est pas. Il devrait vous renvoyer une matrice 2x2; vous affichez son entrée en haut à gauche. Si vous appliquez .corrdirectement à votre dataframe, il renverra toutes les corrélations par paires; c'est pourquoi vous observez alors des 1 à la diagonale de votre matrice (chaque colonne est parfaitement corrélée avec elle-même). Voir ma modification ci-dessous.
Cleb
1
Veuillez envisager d' accepter une réponse si vous pensez qu'elle a répondu à votre question
MaxU
1
J'ai accepté votre réponse, merci
tong zhu
29
Cette question est directement issue du cours "Introduction à la science des données en Python" sur Coursera. Plus précisément, devoir 3, question 9. Lorsque l'instructeur Chris Brooks encourage les étudiants à publier des questions sur Stack Overflow, je ne pense pas qu'il voulait dire qu'ils devraient publier les problèmes des devoirs textuellement.
LS

Réponses:

210

Sans données réelles, il est difficile de répondre à la question, mais je suppose que vous cherchez quelque chose comme ceci:

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

Cela calcule la corrélation entre vos deux colonnes 'Citable docs per Capita' et 'Energy Supply per Capita'.

Pour donner un exemple:

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

ensuite

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

donne 1comme prévu.

Maintenant, si vous modifiez une valeur, par exemple

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

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

la commande

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

Retour

0.99586

qui est toujours proche de 1, comme prévu.

Si vous appliquez .corrdirectement à votre dataframe, il renverra toutes les corrélations par paires entre vos colonnes ; c'est pourquoi vous observez ensuite 1sen diagonale de votre matrice (chaque colonne est parfaitement corrélée avec elle-même).

df.corr()

reviendra donc

          A         B
A  1.000000  0.995862
B  0.995862  1.000000

Dans le graphique que vous montrez, seul le coin supérieur gauche de la matrice de corrélation est représenté (je suppose).

Il peut y avoir des cas où vous obtenez des NaNs dans votre solution - consultez cet article pour un exemple.

Si vous souhaitez filtrer les entrées au-dessus / en dessous d'un certain seuil, vous pouvez cocher cette question . Si vous souhaitez tracer une carte thermique des coefficients de corrélation, vous pouvez vérifier cette réponse et si vous rencontrez ensuite le problème avec des étiquettes d'axes qui se chevauchent, consultez l'article suivant .

Cleb
la source
cela peut-il être appliqué par ligne?
Dr.DOOM
1
@ Dr.DOOM: Oui, cela prend juste des séries, donc par exemple ça df.loc[1, :].corr(df.loc[2, :])fonctionnera bien aussi. Pour l'ensemble dataframe, vous pouvez simplement transposer: df.T.corr().
Cleb
J'ai essayé votre suggestion, mais le calcul renvoie toujours 1 même après avoir changé la valeur a dans la colonne B en utilisant df.loc [2, 'B'] = 4,5. peut-être que je
suis
@ Dr.DOOM: Difficile d'aider car je ne connais pas votre code. Ai-je bien compris que mon exemple ci-dessus revient 1dans votre cas au lieu de 0.99586?
Cleb
1
@Cleb: Eh bien, dans le contexte dans lequel je travaille, chaque index multi-colonnes de niveau supérieur a des sous-couches identiques. Voir cette question pour savoir ce que j'essaie de faire: stackoverflow.com/questions/57513002/…
Adrian Keister
7

J'ai rencontré le même problème. Il est apparu qu'il Citable Documents per Persons'agissait d'un flottant, et python l'ignore d'une manière ou d'une autre par défaut. Toutes les autres colonnes de mon dataframe étaient au format numpy, donc je l'ai résolu en convertissant le columnt ennp.float64

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

N'oubliez pas que c'est exactement la colonne que vous avez calculée vous-même

Gary
la source
6

Ma solution serait après la conversion des données en type numérique:

Top15[['Citable docs per Capita','Energy Supply per Capita']].corr()
ibozkurt79
la source
sélectionner des colonnes puis appliquer la méthode .corr () est une bonne option car nous pouvons calculer la corrélation par paire entre plus de 2 colonnes
Sébastien Wieckowski
4

Si vous voulez les corrélations entre toutes les paires de colonnes, vous pouvez faire quelque chose comme ceci:

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
la source
3

Lorsque vous appelez ceci:

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

Puisque la fonction DataFrame.corr () effectue des corrélations par paire, vous avez quatre paires de deux variables. Donc, fondamentalement, vous obtenez des valeurs diagonales comme corrélation automatique (corrélation avec elle-même, deux valeurs puisque vous avez deux variables), et deux autres valeurs comme corrélations croisées entre l'une et l'autre et vice versa.

Soit effectuer une corrélation entre deux séries pour obtenir une valeur unique:

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)

ou, si vous voulez une seule valeur de la même fonction (corr de DataFrame):

single_value = correlation[0][1] 

J'espère que cela t'aides.

Aumpen
la source
3

Cela fonctionne comme ceci:

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
la source
1

J'ai résolu ce problème en modifiant le type de données. Si vous voyez que «L'approvisionnement en énergie par habitant» est un type numérique, tandis que «Documents à citer par habitant» est un type d'objet. J'ai converti la colonne en float en utilisant un type. J'ai eu le même problème avec certaines fonctions np: count_nonzeroet j'ai sumtravaillé pendant meanet je ne l' stdai pas fait.

OFFRE
la source
0

changer les «documents pouvant être cités par habitant» en numérique avant que la corrélation ne résout le problème.

    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
la source