Я не могу понять, почему sum (df ['series'])! = Df ['series']. Sum () - PullRequest
4 голосов
/ 01 декабря 2019

Я суммирую значения в серии, но в зависимости от того, как я это делаю, я получаю разные результаты. Я попробовал два способа:

sum(df['series'])

df['series'].sum()

Почему они возвращают разные значения?

Пример кода.

s = pd.Series([
0.428229
 , -0.948957
 , -0.110125
 ,  0.791305
 ,  0.113980
 ,-0.479462
 ,-0.623440
 ,-0.610920
 ,-0.135165
 , 0.090192])

 print(s.sum())
 print(sum(s))

 -1.4843630000000003
 -1.4843629999999999

Разница здесь довольно мала,но в наборе данных с несколькими тысячами значений он становится довольно большим.

1 Ответ

3 голосов
/ 01 декабря 2019

Числа с плавающей запятой точны только до определенного числа значащих цифр. Представьте, что все ваши числа, включая промежуточные результаты, точны только до двух значащих цифр, и вам нужна сумма списка [100, 1, 1, 1, 1, 1, 1].

  • «Истинная» сумма равна 106, но это невозможно представить, поскольку нам разрешено использовать только две значащие цифры;
  • "Правильный" ответ: 110 , поскольку это "истинная" сумма, округленная до 2 sf. ;
  • Но если мы наивно добавим числа в последовательности, мы сначала сделаем 100 + 1 = 100 (до 2 нс), затем 100 + 1 = 100 (до 2 нс) и так далее доокончательный результат - 100 .

«Правильный» ответ может быть достигнут путем сложения чисел от наименьшего к наибольшему;1 + 1 = 2, затем 2 + 1 = 3, затем 3 + 1 = 4, затем 4 + 1 = 5, затем 5 + 1 = 6, затем 6 + 100 = 110 (до 2 нс). Тем не менее, даже это не работает в общем случае;если бы их было больше ста, то промежуточные суммы стали бы неточными. Вы можете сделать еще лучше, всегда добавляя наименьшие два оставшихся числа.

Встроенная в Python функция sum использует наивный алгоритм, в то время как метод df['series'].sum() использует более точный алгоритм с меньшей накопленной ошибкой округления. Из исходного кода numy , который использует pandas:

Для чисел с плавающей запятой числовая точность суммы (и np.add.reduce), как правило, ограничивается непосредственным добавлением каждого числа по отдельности. к результату, вызывающему ошибки округления на каждом шаге. Однако часто NumPy использует численно лучший подход (частичное парное суммирование), что приводит к повышению точности во многих случаях использования. Эта улучшенная точность всегда предоставляется, когда не указывается axis.

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 10. * * * * * * * * * * * * * * * * * * * * * * * * * всегда на * * * *. 1036 * В отличие от NumPy, функция Python math.fsum использует более медленный, но более точный подход к суммированию.

Для вашего списка результат math.fsum равен -1.484363, что является правильнымобоснованный ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...