Hm, troque onde eu falei "multiplicação" no comentário anterior por "potenciação", claro... :/
July 17, 2008 at 10:10 PM
Este post segue uma seqüência iniciada no blog Kodumaro, comparando a implementação de alguns cálculos de estatística usando linguagens como Lisp, C e depois seguido de Ruby no blog Programando sem cafeína, e Smalltalk.
Como estou vendo um pouco de estatística na faculdade agora, me animei para tentar uma implementação em Python também.
import math
def arithmetic_mean(dataset): """ Simple arithmetic mean (average)
Example: >>> root_mean_square([10,100,1000]) 580.25856305616037 """ return math.sqrt(sum(x**2 for x in dataset) / len(dataset))
def var_num(dataset, mean_function=arithmetic_mean): """ Divisor for variance calculation """ mean = mean_function(dataset) return sum((x - mean)**2 for x in dataset)
def populational_variance(dataset): """ Population variance
Preferi implementar como funções simples pois assim é fácil de aplicar sobre qualquer conjunto de dados iterável como listas, tuplas, dicionários ou sets.
Na função de numerador da variância, um dos parâmetros é a função de média que se deseja utilizar para o cálculo, com o padrão sendo a média aritmética (pois como nota o blog Kodumaro, o uso da função depende de quem pediu o cálculo ;).
Vale notar também o uso de generator expressions para os somatórios, que substituem as mais tradicionais list comprehensions nesse caso por questão de performance, principalmente para grandes conjuntos de dados.
Apliquei ainda doctests simples para validar os resultados das funções.
"Cálculo da variância em Python"
7 Comments -
Ficou muito boa essa versão em Python
June 10, 2008 at 2:00 AM
Muito legal! Também gostei. =)
Só não entendi por que você usou math.sqrt().
Geralmente faço isso com pow() ou com **.
Qual o motivo de sua escolha? Há alguma diferença de precisão ou desempenho?
[]'s
Cacilhas, La Batalema
June 10, 2008 at 6:32 AM
Não entendi a dúvida. Como você calcula a raiz usando potência?
Prefiro usar métodos prontos do que reimplementar na maioria dos casos. A biblioteca Python é extensa e "não tenho medo de usar" :D
June 10, 2008 at 6:46 PM
A operação de "raiz" é uma potenciação, só que com um valor fracionário.
math.pow(10, 0.5) == math.sqrt(10)
Mas é claro que pra raízes quadradas, math.sqrt é muito mais intuitivo ;)
Parabéns pelo post, foi bem interessante!
June 13, 2008 at 11:08 AM
Tem razão ! *slaps own forehead* :)
Rodei alguns testes aqui, e a versão utilizando multiplicação é mais rápida, como pode ser visto ao rodar este código:
from timeit import Timer
print 'multiply:'
print min(Timer('10**0.5').repeat())
print 'math.sqrt:'
print min(Timer('sqrt(10)', 'from math import sqrt').repeat())
Aqui o resultado é:
multiply:
0.0717430114746
math.sqrt:
0.43367600441
Portanto, para quem quiser otimizar um pouco o código, pode trocar pela multiplicação mesmo.
O custo maior do math.sqrt ocorre por se tratar de uma chamada de função, que envolve busca no namespace:
"Function call overhead in Python is relatively high, especially compared with the execution speed of a builtin function." [1]
e nisso a operação de multiplicação direta leva vantagem.
June 13, 2008 at 10:41 PM
Bacana ;)
July 2, 2008 at 7:26 AM
Hm, troque onde eu falei "multiplicação" no comentário anterior por "potenciação", claro... :/
July 17, 2008 at 10:10 PM