res = (sum([(xi-mx)*(yi-my) for xi in x for yi in y]))/(len(x)*sdx*sdy)
Это не делает то, что вы думаете, что делает. При расчете числителя коэффициента корреляции Пирсона, (xi - mx) * (yi - my)
должно быть спарено последовательно.
Использование zip
должно исправить это.
res = (sum([(xi-mx)*(yi-my) for xi, yi in zip(x, y)]))/(len(x)*sdx*sdy)
Вот что я получаю:
def r(x, y):
mx, my = sum(x) / len(x), sum(y) / len(y)
sdx, sdy = (sum([(xi-mx)**2 for xi in x]) / len(x))**0.5, (sum([(yi-
my)**2 for yi in y]) / (len(y)))**0.5
res = (sum([(xi-mx)*(yi-my) for xi, yi in zip(x, y)]))/(len(x)*sdx*sdy)
return res
r(x, y) # 0.6124721937208479
Что на самом деле делает for xi in x for yi in y
>>> x, y = [1, 2, 3], [4, 5, 6]
>>> [(xi, yi) for xi in x for yi in y]
[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]
Так что повторение продолжается. (Фактически создание списка комбинаций.) Вы можете использовать zip
для объединения значений в пары:
>>> [*zip(x, y)]
[(1, 4), (2, 5), (3, 6)]