Используйте .corr, чтобы получить корреляцию между двумя столбцами


128

У меня есть следующий фреймворк pandas 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?
Щипцы чжу

1
Это не. Он должен вернуть вам матрицу 2x2; вы показываете его левую верхнюю запись. Если вы примените .corrнепосредственно к вашему фрейму данных, он вернет все парные корреляции; вот почему вы затем наблюдаете единицы на диагонали вашей матрицы (каждый столбец идеально коррелирует с самим собой). Смотрите мою правку ниже.
Cleb

1
Пожалуйста , обратите внимание принимая ответ , если вы думаете , что ответил на ваш вопрос
MaxU

1
Я принял ваш ответ, спасибо
Щипцы чж

29
Этот вопрос прямо из курса «Введение в науку о данных в Python» на Coursera. В частности, задание 3, вопрос 9. Когда преподаватель Крис Брукс призывает студентов публиковать вопросы в 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непосредственно к фрейму данных, он вернет все попарные корреляции между вашими столбцами ; поэтому вы затем наблюдаете 1sпо диагонали своей матрицы (каждый столбец идеально коррелирует с самим собой).

df.corr()

поэтому вернется

          A         B
A  1.000000  0.995862
B  0.995862  1.000000

На графике, который вы показываете, представлен только верхний левый угол корреляционной матрицы (я полагаю).

Могут быть случаи, когда вы получаете NaNs в своем решении - посмотрите этот пост для примера.

Если вы хотите отфильтровать записи выше / ниже определенного порога, вы можете проверить этот вопрос . Если вы хотите построить тепловую карту коэффициентов корреляции, вы можете проверить этот ответ, и если вы затем столкнетесь с проблемой с перекрывающимися метками осей, проверьте следующий пост .


можно ли это применить по строкам?
Доктор ДУМ

1
@ Доктор ДУМ: Да, для этого нужны просто серии, так что, например df.loc[1, :].corr(df.loc[2, :]), тоже будет работать нормально. Для всего dataframe, вы можете просто перенести: df.T.corr().
Cleb

Я попробовал ваше предложение, однако вычисление по-прежнему возвращает 1 даже после изменения значения a в столбце B с помощью df.loc [2, 'B'] = 4.5. возможно, я просто запутался в вычислениях
Доктор ДУМ

@ Доктор ДУМ: Трудно помочь, потому что я не знаю вашего кода. Правильно ли я понял, что мой пример сверху возвращается 1в вашем случае вместо 0.99586?
Cleb

1
@Cleb: Ну, в контексте, в котором я работаю, каждый многостолбцовый индекс более высокого уровня имеет идентичные подуровни. См. Этот вопрос о том, что я пытаюсь сделать: stackoverflow.com/questions/57513002/…
Адриан

7

Я столкнулся с той же проблемой. Оказалось, что Citable Documents per Personэто поплавок, и python как-то его пропускает по умолчанию. Все остальные столбцы моего фрейма данных были в формате numpy, поэтому я решил это, преобразовав столбец в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()

выбор столбцов с последующим применением метода .corr () - хороший вариант, так как мы можем вычислить корреляцию попарно между более чем двумя столбцами,
Себастьян

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)

или, если вам нужно одно значение из той же функции (Corr DataFrame):

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

Я решил эту проблему, изменив тип данных. Если вы видите, что «Энергоснабжение на душу населения» - это числовой тип, а «Цитируемые документы на душу населения» - это тип объекта. Я преобразовал столбец в float, используя 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')
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.