2017-02-21 18 views
1

У меня возникла какая-то странная проблема с использованием spearmanr из scipy.stats. Я использую значения полинома, чтобы получить некоторые корреляции, которые немного интереснее для работы, но если бы я вручную вводил значения (как список, преобразованный в массив numpy), я получаю другую корреляцию с тем, что я получаю если я вычисляю значения с помощью функции. Приведенный ниже код должен продемонстрировать, что я имею в виду:Различные результаты от scipy.stats.spearmanr в зависимости от того, как создаются данные

import numpy as np 
from scipy.stats import spearmanr  
data = np.array([ 0.4, 1.2, 1. , 0.4, 0. , 0.4, 2.2, 6. , 12.4, 22. ]) 
axis = np.arange(0, 10, dtype=np.float64) 

print(spearmanr(axis, data))# gives a correlation of 0.693... 

# Use this polynomial 
poly = lambda x: 0.1*(x - 3.0)**3 + 0.1*(x - 1.0)**2 - x + 3.0 

data2 = poly(axis) 
print(data2) # It is the same as data 

print(spearmanr(axis, data2))# gives a correlation of 0.729... 

Я заметил, что массивы несколько отличаются (т.е. data - data2 не в точности равна нулю для всех элементов), но разница очень мала - порядка 1e-16.

Является ли такое крошечное различие достаточным, чтобы отбросить копьеносца этим?

ответ

1

Является ли такое крошечное различие достаточным, чтобы отбросить копейщика?

Да, потому что г Спирмена основан на ранге образца. Такие маленькие различия могут изменить ранг значений, которые иначе были бы равны:

sp.stats.rankdata(data) 
# array([ 3., 6., 5., 3., 1., 3., 7., 8., 9., 10.]) 
# Note that all three values of 0.4 get the same rank 3. 

sp.stats.rankdata(data2) 
# array([ 2.5, 6. , 5. , 2.5, 1. , 4. , 7. , 8. , 9. , 10. ]) 
# Note that two values 0.4 get the rank 2.5 and one gets 4. 

Если добавить небольшой градиент (больше, чем численной разницы вы наблюдаете), чтобы разорвать такие связи, вы получите тот же результат:

print(spearmanr(axis, data + np.arange(10)*1e-12)) 
# SpearmanrResult(correlation=0.74545454545454537, pvalue=0.013330146315440047) 

print(spearmanr(axis, data2 + np.arange(10)*1e-12)) 
# SpearmanrResult(correlation=0.74545454545454537, pvalue=0.013330146315440047) 

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