计算字符串列之间的相关性

22

我有一个包含职业和媒体两列的数据框df。我想计算这两列之间的相关性。

有没有一种简短的方法来计算字符串列的相关性?或者我需要将每个职业和媒体转换为数字,然后使用.corr()计算相关性?

我找到了一个类似的问题(Is there a way to get correlation with string data and a numerical value in pandas?),但我想检查整个字符串,而不仅仅是字符串中的每个单词。

df

  profession        media      

0 media lawyer      print
1 student           online
2 student           print
3 professor         online
4 media lawyer      online
2个回答

37

你可以将数据类型转换为分类,然后进行操作。

df['profession']=df['profession'].astype('category').cat.codes
df['media']=df['media'].astype('category').cat.codes
df.corr()

3
你能为这个答案提供一些解释吗?它运行得很好,我只是想知道为什么要使用“.cat.codes”,以及“.codes”是什么意思? - Rasika
4
.cat.codes 将您的类别从字符串表示转换为整数表示。例如,“媒体律师”将被替换为0,“学生”将被替换为1,“教授”将被替换为2。在另一列中,“打印”将被替换为0,“在线”将被替换为1。 - Corey Levinson
3
这个有意义吗?因为如果我们有超过2个字符串值,这可能会产生0、1和2三种类别,并且它可能会解释2比1离0更远...不确定我是否表达清楚。 - J Agustin Barrachina

0
正如@JAgustinBarrachina所指出的,接受的答案在底层使用了皮尔逊相关系数方法,这导致了一种偏见。每列的分类可能产生以下结果:
- 媒体律师 --> 0 - 学生 --> 1 - 教授 --> 2
由于皮尔逊方法计算线性相关性,它会计算每个类别之间的距离。从算法的角度来看,一个"媒体律师"与一个"教授"之间的距离(2 - 0 = 2)会比它与一个"学生"之间的距离(1 - 0 = 1)更大。然而,在这种情况下,这并不正确,因此得出的相关性将会有偏差。

从文档中还有另外两种相关性方法可用:Kendall和Spearman方法。但它们都假设类别是有序的。 例如,类别revenue : ["low", "medium", "high"]可以被视为有序。

如果一列的类别之间没有顺序关系,使用Chi²和Cramér's V方法更为合适:

import scipy.stats as ss
import pandas as pd
from pandas import DataFrame, Series

profession_and_media = DataFrame(data = {
    # Decupling data to simulate significance
    "profession" : ["media lawyer" , "student" , "student" , "professor" , "media lawyer"] * 10,
    "media" : ["print" , "online" , "print" , "online" , "online"] * 10
    })

def cramers_corrected_stat(columnA: Series, columnB: Series):
    """ calculate Cramers V statistic for categorial-categorial association.
        uses correction from Bergsma and Wicher, 
        Journal of the Korean Statistical Society 42 (2013): 323-328
    """
    confusion_matrix = pd.crosstab(columnA, columnB)
    chi2 = ss.chi2_contingency(confusion_matrix)[0]
    n = confusion_matrix.to_numpy().sum(axis=None)
    phi2 = chi2/n
    r,k = confusion_matrix.shape
    phi2corr = max(0, phi2 - ((k-1)*(r-1))/(n-1))    
    rcorr = r - ((r-1)**2)/(n-1)
    kcorr = k - ((k-1)**2)/(n-1)
    return np.sqrt(phi2corr / min( (kcorr-1), (rcorr-1)))


def compute_category_correlation(df: DataFrame):
    """ Compute the correlation between string columns of a DataFrame
    """
    for column in df.columns:
        df.loc[:, column] = df[column].astype('category').cat.codes
    result = df.corr(method=cramers_corrected_stat)
    return result.style.background_gradient(cmap='Reds')

compute_category_correlation(profession_and_media)

这给出了
职业与媒体之间的相关矩阵


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接