Usa .corr per ottenere la correlazione tra due colonne


127

Ho il seguente dataframe panda Top15: inserisci qui la descrizione dell'immagine

Creo una colonna che stima il numero di documenti citabili per persona:

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

Voglio conoscere la correlazione tra il numero di documenti citabili pro capite e l'approvvigionamento energetico pro capite. Quindi utilizzo il .corr()metodo (correlazione di Pearson):

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

Voglio restituire un singolo numero, ma il risultato è: inserisci qui la descrizione dell'immagine


Penso che tu abbia ragione. Ma puoi dirmi perché 'data.corr (method =' pearson ')' restituisce solo la relazione tra Energy Supply e Energy Suppy?
tong zhu

1
Non è così. Dovrebbe restituirti una matrice 2x2; mostri la sua voce in alto a sinistra. Se applichi .corrdirettamente al tuo dataframe, restituirà tutte le correlazioni a coppie; ecco perché poi osservi 1s sulla diagonale della tua matrice (ogni colonna è perfettamente correlata con se stessa). Vedi la mia modifica di seguito.
Cleb

1
Considera la possibilità di accettare una risposta se pensi che abbia risposto alla tua domanda
MaxU

1
Ho accettato la tua risposta, grazie
tong zhu

29
Questa domanda proviene direttamente dal corso "Introduzione alla scienza dei dati in Python" su Coursera. In particolare, compito 3, domanda 9. Quando l'istruttore Chris Brooks incoraggia gli studenti a inviare domande a Stack Overflow, non credo che intendesse che avrebbero dovuto pubblicare i problemi dei compiti alla lettera.
LS

Risposte:


210

Senza dati reali è difficile rispondere alla domanda, ma immagino che tu stia cercando qualcosa del genere:

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

Questo calcola la correlazione tra le tue due colonne 'Citable docs per Capita' e 'Energy Supply per Capita'.

Per fare un esempio:

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

Poi

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

1come previsto.

Ora, se modifichi un valore, ad es

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

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

il comando

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

ritorna

0.99586

che è ancora vicino a 1, come previsto.

Se applichi .corrdirettamente al tuo dataframe, restituirà tutte le correlazioni a coppie tra le tue colonne ; ecco perché poi osservi 1salla diagonale della tua matrice (ogni colonna è perfettamente correlata con se stessa).

df.corr()

tornerà quindi

          A         B
A  1.000000  0.995862
B  0.995862  1.000000

Nel grafico che mostri, è rappresentato solo l'angolo superiore sinistro della matrice di correlazione (presumo).

Ci possono essere casi in cui ottieni messaggi di postaNaN elettronica nella tua soluzione: controlla questo post per un esempio.

Se vuoi filtrare le voci sopra / sotto una certa soglia, puoi controllare questa domanda . Se vuoi tracciare una mappa termica dei coefficienti di correlazione, puoi controllare questa risposta e se poi incontri il problema con le etichette degli assi sovrapposte controlla il seguente post .


può essere applicato per riga?
Dr. DOOM

1
@ Dr.DOOM: Sì, ci vogliono solo serie, quindi anche df.loc[1, :].corr(df.loc[2, :])funzionerà bene. Per l'intero dataframe, si può semplicemente trasporre: df.T.corr().
Cleb

Ho provato il tuo suggerimento, tuttavia il calcolo restituisce ancora 1 anche dopo aver modificato il valore a nella colonna B utilizzando df.loc [2, 'B'] = 4.5. forse sono solo confuso sul calcolo
Dr.DOOM

@ Dr.DOOM: Difficile da aiutare perché non conosco il tuo codice. Ho capito bene che il mio esempio dall'alto ritorna 1nel tuo caso invece di 0.99586?
Cleb

1
@ Cleb: Beh, nel contesto in cui sto lavorando, ogni indice multi-colonna di livello superiore ha sottostrati identici. Vedi questa domanda per quello che sto cercando di fare: stackoverflow.com/questions/57513002/…
Adrian Keister

7

Mi sono imbattuto nello stesso problema. Sembrava Citable Documents per Personfosse un float e Python lo salta in qualche modo per impostazione predefinita. Tutte le altre colonne del mio dataframe erano in formati numpy, quindi l'ho risolto convertendo la colonna innp.float64

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

Ricorda che è esattamente la colonna che hai calcolato tu stesso


6

La mia soluzione sarebbe dopo aver convertito i dati in tipo numerico:

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

selezionare le colonne e quindi applicare il metodo .corr () è una buona opzione in quanto possiamo calcolare la correlazione a coppie tra più di 2 colonne
Sébastien Wieckowski

4

Se vuoi le correlazioni tra tutte le coppie di colonne, potresti fare qualcosa del genere:

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

Quando lo chiami:

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

Poiché la funzione DataFrame.corr () esegue correlazioni a coppie, hai quattro coppie da due variabili. Quindi, fondamentalmente stai ottenendo valori diagonali come correlazione automatica (correlazione con se stesso, due valori poiché hai due variabili) e altri due valori come correlazioni incrociate l'uno rispetto all'altro e viceversa.

Eseguire la correlazione tra due serie per ottenere un singolo valore:

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)

oppure, se vuoi un singolo valore dalla stessa funzione (corr di DataFrame):

single_value = correlation[0][1] 

Spero che questo ti aiuti.


3

Funziona così:

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

Ho risolto questo problema cambiando il tipo di dati. Se vedi che "Energy Supply pro capite" è un tipo numerico mentre "Citable docs pro capite" è un tipo di oggetto. Ho convertito la colonna in float usando astype. Ho avuto lo stesso problema con alcune funzioni NP: count_nonzeroe sumlavorato, mentre meane stdnon l'ha fatto.


0

cambiare "Citable docs pro capite" in numerico prima della correlazione risolverà il problema.

    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')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.