Użyj .corr, aby uzyskać korelację między dwiema kolumnami

128

Mam następującą ramkę danych pandy Top15: wprowadź opis obrazu tutaj

Tworzę kolumnę, która szacuje liczbę cytowanych dokumentów na osobę:

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

Chcę poznać korelację między liczbą cytowanych dokumentów na mieszkańca a podażą energii na mieszkańca. Więc używam .corr()metody (korelacja Pearsona):

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

Chcę zwrócić jedną liczbę, ale wynik jest taki: wprowadź opis obrazu tutaj

tong zhu
źródło
Myślę, że masz rację. Ale czy możesz mi powiedzieć, dlaczego 'data.corr (metoda =' pearson ')' zwraca tylko związek między dostawami energii a zaopatrzeniem w energię?
tong zhu
1
To nie. Powinien zwrócić macierz 2x2; pokazujesz jego lewy górny wpis. Jeśli zastosujesz się .corrbezpośrednio do swojej ramki danych, zwróci ona wszystkie korelacje parami; dlatego następnie obserwujesz jedynki na przekątnej swojej macierzy (każda kolumna jest ze sobą doskonale skorelowana). Zobacz moją edycję poniżej.
Cleb
1
Rozważ przyjęcie odpowiedzi, jeśli uważasz, że odpowiedziała na Twoje pytanie
MaxU
1
Przyjąłem twoją odpowiedź, dziękuję
tong zhu
29
To pytanie pochodzi prosto z kursu „Wprowadzenie do nauki o danych w Pythonie” na Coursera. W szczególności zadanie 3, pytanie 9. Kiedy instruktor Chris Brooks zachęca uczniów do zadawania pytań na Stack Overflow, nie sądzę, że miał na myśli, że powinni pisać problemy z zadań.
LS

Odpowiedzi:

210

Bez faktycznych danych trudno odpowiedzieć na pytanie, ale myślę, że szukasz czegoś takiego:

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

To oblicza korelację między twoimi dwiema kolumnami 'Citable docs per Capita' i 'Energy Supply per Capita'.

Dać przykład:

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

Następnie

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

daje 1zgodnie z oczekiwaniami.

Teraz, jeśli zmienisz wartość, np

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

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

Komenda

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

zwroty

0.99586

która nadal jest bliska 1, zgodnie z oczekiwaniami.

Jeśli zastosujesz się .corrbezpośrednio do swojej ramki danych, zwróci ona wszystkie korelacje parami między kolumnami ; dlatego obserwujesz następnie 1sprzekątną swojej macierzy (każda kolumna jest ze sobą doskonale skorelowana).

df.corr()

dlatego powróci

          A         B
A  1.000000  0.995862
B  0.995862  1.000000

Na przedstawionej grafice przedstawiony jest tylko lewy górny róg macierzy korelacji (zakładam).

Mogą wystąpić przypadki, w których otrzymasz NaNs w swoim rozwiązaniu - sprawdź przykład w tym poście .

Jeśli chcesz filtrować wpisy powyżej / poniżej określonego progu, możesz sprawdzić to pytanie . Jeśli chcesz wykreślić mapę cieplną współczynników korelacji, możesz sprawdzić tę odpowiedź, a jeśli następnie napotkasz problem z nakładającymi się etykietami osi, sprawdź następujący post .

Cleb
źródło
czy można to zastosować według rzędu?
Dr DOOM
1
@ Dr.DOOM: Tak, to wymaga tylko serii, więc np. Też df.loc[1, :].corr(df.loc[2, :])będzie działać dobrze. Przez cały dataframe, można po prostu transpozycji: df.T.corr().
Cleb
Wypróbowałem twoją sugestię, jednak obliczenia nadal zwracają 1, nawet po zmianie wartości a w kolumnie B przy użyciu df.loc [2, „B”] = 4,5. może
jestem
@ Dr.DOOM: Trudno jest pomóc, ponieważ nie znam twojego kodu. Czy dobrze zrozumiałem, że mój przykład z góry 1w twoim przypadku wraca zamiast 0.99586?
Cleb
1
@Cleb: Cóż, w kontekście, w którym pracuję, każdy indeks wielokolumnowy wyższego poziomu ma identyczne podwarstwy. Zobacz to pytanie, aby dowiedzieć się, co próbuję zrobić: stackoverflow.com/questions/57513002/…
Adrian Keister
7

Napotkałem ten sam problem. Wyglądało na Citable Documents per Personto, że jest to float, a Python jakoś domyślnie go pomija. Wszystkie inne kolumny mojej ramki danych były w formacie numpy, więc rozwiązałem to, konwertując kolumnę nanp.float64

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

Pamiętaj, że to dokładnie ta kolumna, którą sam obliczyłeś

Gary
źródło
6

Moje rozwiązanie byłoby po konwersji danych na typ liczbowy:

Top15[['Citable docs per Capita','Energy Supply per Capita']].corr()
ibozkurt79
źródło
wybranie kolumn, a następnie zastosowanie metody .corr () jest dobrą opcją, ponieważ możemy obliczyć korelację parami między więcej niż 2 kolumnami
Sébastien Wieckowski
4

Jeśli chcesz uzyskać korelacje między wszystkimi parami kolumn, możesz zrobić coś takiego:

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
źródło
3

Kiedy nazywasz to:

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

Ponieważ funkcja DataFrame.corr () wykonuje korelacje parami, masz cztery pary z dwóch zmiennych. Tak więc, zasadniczo otrzymujesz wartości przekątne jako autokorelację (korelacja ze sobą, dwie wartości, ponieważ masz dwie zmienne), a pozostałe dwie wartości jako korelacje krzyżowe między sobą i odwrotnie.

Aby uzyskać jedną wartość, wykonaj korelację między dwiema seriami:

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)

lub, jeśli chcesz pojedynczą wartość z tej samej funkcji (Corr DataFrame):

single_value = correlation[0][1] 

Mam nadzieję że to pomoże.

aumpen
źródło
3

Działa to tak:

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
źródło
1

Rozwiązałem ten problem, zmieniając typ danych. Jeśli zobaczysz, że „Dostarczanie energii na mieszkańca” jest typem liczbowym, a „Dokumenty do cytowania na mieszkańca” to typ obiektu. Przekonwertowałem kolumnę na zmiennoprzecinkową przy użyciu astype. Miałem ten sam problem z niektórymi funkcjami np: count_nonzeroi sumpracowałem podczas, meana stdnie.

OFERTA
źródło
0

zmiana „Citable docs per capita” na numeryczne, zanim korelacja rozwiąże problem.

    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
źródło