Я экспериментировал с набором данных о мошенничестве с кредитными картами, который бесплатно доступен на 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]