Почему добавление / удаление большего количества функций в Pandas DataFrame изменяет его p-значение парной корреляции Пирсона? - PullRequest
0 голосов
/ 26 марта 2020

Я экспериментировал с набором данных о мошенничестве с кредитными картами, который бесплатно доступен на Kaggle . Чтобы дать общее представление, он в основном содержит от «V1» до «V28», функции, которые были сокращены по PCA, и «Amount», который представляет собой сумму транзакции.

При запуске Pandas pd .DataFrame.corr () в наборе данных, я попытался найти некоторые корреляции Пирсона, используя встроенный метод корреляции Пирсона и p-значения, используя scipy.stats.pearsonr.

Однако, кажется, что когда я Попробуйте сделать это, либо отбросив случайный объект (например, «V3»), либо добавив новый объект, полученный с помощью sklearn.preprocessing.RobustScaler, для функции «Количество», в то время как парная корреляция не изменится, как ожидается, p-значение корреляция, похоже, меняется.

corr_finder(df, p_value=True)
# Printed results:
# (1, 28) V2 has a correlation of -0.5314 with Amount with p-value of 0.0
# (4, 28) V5 has a correlation of -0.3864 with Amount with p-value of 0.0031
# (6, 28) V7 has a correlation of 0.3973 with Amount with p-value of 0.0026
# (19, 28) V20 has a correlation of 0.3394 with Amount with p-value of 0.0108

Отбрасывание 'V3':

corr_finder(df.drop('V3', axis=1), p_value=True)
# Printed results:
# (1, 27) V2 has a correlation of -0.5314 with Amount with p-value of 0.0
# (3, 27) V5 has a correlation of -0.3864 with Amount with p-value of 0.003
# (5, 27) V7 has a correlation of 0.3973 with Amount with p-value of 0.0032
# (18, 27) V20 has a correlation of 0.3394 with Amount with p-value of 0.0126

Добавление надежного масштабированного значения 'Amount':

df['A_rbscale'] = RobustScaler().fit_transform(df['Amount'].values.reshape(-1, 1))
corr_finder(df, p_value=True)
# Printed results:
# (1, 28) V2 has a correlation of -0.5314 with Amount with p-value of 0.0
# (4, 28) V5 has a correlation of -0.3864 with Amount with p-value of 0.0004
# (6, 28) V7 has a correlation of 0.3973 with Amount with p-value of 0.0005
# (19, 28) V20 has a correlation of 0.3394 with Amount with p-value of 0.0031
# (1, 29) V2 has a correlation of -0.5314 with A_rbscale with p-value of 0.0
# (4, 29) V5 has a correlation of -0.3864 with A_rbscale with p-value of 0.0004
# (6, 29) V7 has a correlation of 0.3973 with A_rbscale with p-value of 0.0005
# (19, 29) V20 has a correlation of 0.3394 with A_rbscale with p-value of 0.0031
# (28, 29) Amount has a correlation of 1.0 with A_rbscale with p-value of 0.0

Я ошибаюсь в фундаментальной аспект корреляции, это результат причуды Pandas или это может быть ошибка в моем коде? У меня сложилось впечатление, что, поскольку число наблюдений для каждого объекта в каждом расчете парной корреляции одинаково во всех трех случаях, его значение p (вероятность, при которой рассчитанная корреляция является истинной, учитывая, что эти два объекта фактически не коррелированы) не должно меняться.

Это наблюдение на самом деле не ограничивается только корреляцией Пирсона, но также и когда я устанавливаю метод вычисления p-значения также на Спирмена.

Ниже приведен код функция, которую я определил как corr_finder:

def corr_finder(df, threshold=0.3, get_list=False, p_value=False, method=None):
    if method is None:
        method = 'pearson'

    df = df.corr(method=method)

    # Calculate p-values if requested
    if p_value:
        if method == 'pearson':
            df_pv = df.corr(method=pearsonr_pval)
        elif method == 'spearman':
            df_pv = df.corr(method=spearmanr_pval)
        elif method == 'kendall':
            df_pv = df.corr(method=kendall_pval)

    corr_list = list()

    # Combination of for statements add up to iterate through all matrices of the 
    # bottom-left triangular half of the correlation matrix
    for y in range(1, df.shape[1]):
        for x in range(0, y):

            # If correlation is above given threshold
            if abs(df.iloc[x, y]) > threshold:

                # If p-value is desired, print it together with correlation and coordinates
                if p_value:
                    print('({}, {})'.format(x, y), '{} has a correlation of'.format(df.columns[x]), 
                          round(df.iloc[x, y], 4), 'with {}'.format(df.columns[y]),
                         'with p-value of', round(df_pv.iloc[x, y], 4))
                else:
                    print('({}, {})'.format(x, y), '{} has a correlation of'.format(df.columns[x]), 
                          round(df.iloc[x, y], 4), 'with {}'.format(df.columns[y]))

                # If a list was requested to be returned
                if get_list:
                    # Add p-value into list if it is desired
                    if p_value:
                        corr_list.append([x, y, round(df.iloc[x, y], 4), round(df_pv.iloc[x, y], 4)])
                    else:
                        corr_list.append([x, y, round(df.iloc[x, y], 4)])


    return corr_list

pearsonr_pval просто

def pearsonr_pval(x,y):
    return pearsonr(x,y)[1]
...