2015-01-29 6 views
2

Я тестирую симуляцию на лайтерах, таким образом, что я ожидаю, что калоудация на заданную дату вернет такое же число, независимо от датеранга который я рассчитываю для данной партии.Nump, pandas, Matlab, R несоответствие суммарной суммы, с разной продолжительностью истории

То есть, если я позвоню системе для диапазона 1990-2000, то результат 1995.07.01 должен быть таким же, как при вызове системы на 1995-1996 годы. Должно быть достаточно базовым, я подумал ...

Проблема в том, что быстрые свертывающие окна реализуют ошибки округления, которые зависят от длины истории за пределами окна качения. Поэтому, когда я делаю 20-дневную скользящую сумму за 1995.07.01, результат будет иметь большую скопированную ошибку округления в случае запуска операции сальниковой суммы на тайм-сервере с 1990 года.

Вот пример, где я ожидал бы не-нан результаты точно соответствовать:

df = pd.DataFrame([xrange(7)]).astype('float64').T 
df = np.sqrt(df) 
roll1_df = pd.rolling_sum(df, window=3) 
roll2_df = pd.rolling_sum(df.iloc[3:, :], window=3) 

но я получаю ошибку округления:

roll1_df - roll2_df 

       0 
0   NaN 
1   NaN 
2   NaN 
3   NaN 
4   NaN 
5 8.881784e-16 
6 1.776357e-15 

пример использует Python/панд, но проблема та же в любой номер хруст программного обеспечения, поэтому я рад за идеи, в пандах, numpy, Matlab, R ... или bas по чистой теории.

Было бы важно сохранить преимущество производительности операций быстрой прокатки, т. Е. Избегать простого суммирования последних значений N для всех дат (что будет в O (N) раза медленнее, чем более быстрые версии развертывания качения).

Edit: Решение

Я выбрал следующее решение в конце концов, принимая панда друг от друга и положить обратно вместе с небольшим количеством округления в rolling_sum:

rolling_sum_stable_df = _rolling_func(
    lambda *arg_l: np.round(roll_sum(*arg_l), decimals=11), 
    'Stable rolling_sum' 
) 

удалось преобразовать в float32 первого перед тем rolling_sum(), а затем конвертировать обратно в float64, но затем потеряет больше цифр. Недостатком подхода является то, что я должен сделать это для roll_cov и других функций качения, которые немного больше задействованы.

+1

Я не совсем уверен, что понимаю, что именно вы суммируете. Но если вы хотите точное равенство между двумя результатами, то число чисел с плавающей запятой никогда не сделает вас счастливыми. Вам придется либо использовать целые типы, либо реализовать «почти равные», а не «равные». – sebastian

+1

Вы можете использовать ['np.isclose'] (http://docs.scipy.org/doc/numpy/reference/generated/numpy.isclose.html):' np.isclose (roll1_df [3:], roll2_df) 'Это показывает, что последние 2 значения достаточно близки, чтобы считаться равными. – EdChum

+0

Пробовал это несколько лет назад. К сожалению, числовые ошибки нелинейны в системе, т. Е. Разница 1е-16 может вызвать большие изменения в более поздних числах. –

ответ

1

Используйте встроенный модуль python decimal. Он не имеет ошибок округления с плавающей запятой. Тем не менее, он медленнее, чем числа с плавающей запятой.

+0

Хорошая идея, но не могла позволить ей работать внутри панд. –