1

Is there a way to use it like

Foo.objects.annotate(geometric_mean=GeometricMean('bars__value'))

or

Foo.objects.annotate(geometric_mean=Power(Prod('bars__value'), Count('bars'))
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
SeokJun Yeom
  • 401
  • 1
  • 4
  • 9

1 Answers1

3

You can do something quite similar: you can calculate the average of the natural logarithms:

from django.db.models import Avg
from django.db.models.functions import Ln

Foo.objects.annotate(geometric_mean=Avg(Ln('bars__value')))

then the geometric mean is the exponent of this. If you really need the geometric mean itself, then you can use Exp [Django-doc] on that result:

from django.db.models import Avg
from django.db.models.functions import Exp, Ln

Foo.objects.annotate(geometric_mean=Exp(Avg(Ln('bars__value'))))

but you do not need this if you for example only want to order by two geometric means, since the exponent leaves the order relation intact: ea≤eb implies a≤b and vice versa.

This works because ln(x1×x2×…×xn) is equivalent to ln(x1)+ln(x2)+…+ln(xn), and ln(xy) is equivalent to y×ln(x).

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555