Amélioration statistiques
This commit is contained in:
		
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -42,6 +42,8 @@ from icalendar import Event as icalEvent
 | 
			
		||||
from location_field.models.spatial import LocationField
 | 
			
		||||
from django.dispatch import receiver
 | 
			
		||||
from django.db.models.signals import post_save
 | 
			
		||||
from django.db.models.aggregates import StdDev
 | 
			
		||||
from django.db.models import Avg, Max, Min
 | 
			
		||||
 | 
			
		||||
from .calendar import CalendarDay
 | 
			
		||||
from .import_tasks.extractor import Extractor
 | 
			
		||||
@@ -49,9 +51,24 @@ from .import_tasks.generic_extractors.fbevent import (
 | 
			
		||||
    CExtractor as FacebookEventExtractor,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
from django.db.models import Aggregate, FloatField
 | 
			
		||||
 | 
			
		||||
logger = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Median(Aggregate):
 | 
			
		||||
    function = "PERCENTILE_CONT"
 | 
			
		||||
    name = "median"
 | 
			
		||||
    output_field = FloatField()
 | 
			
		||||
    template = "%(function)s(0.5) WITHIN GROUP (ORDER BY %(expressions)s)"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
#
 | 
			
		||||
# Useful for translation
 | 
			
		||||
to_be_translated = [_("mean"), _("median"), _("maximum"), _("minimum"), _("stdev")]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class UserProfile(models.Model):
 | 
			
		||||
    user = models.OneToOneField(
 | 
			
		||||
        User,
 | 
			
		||||
@@ -2728,26 +2745,38 @@ class RecurrentImport(models.Model):
 | 
			
		||||
        else:
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
    def get_foresight_quality(self):
 | 
			
		||||
        from statistics import median, mean, stdev
 | 
			
		||||
    def _get_foresight_quality_internal(qs):
 | 
			
		||||
        limit = datetime.now() + timedelta(days=-30)
 | 
			
		||||
 | 
			
		||||
        values = [
 | 
			
		||||
            x["foresight"]
 | 
			
		||||
            for x in Event.objects.filter(import_sources__contains=[self.source])
 | 
			
		||||
            .annotate(foresight=ExtractDay(F("start_day") - F("created_date")))
 | 
			
		||||
            .values("foresight")
 | 
			
		||||
        ]
 | 
			
		||||
        if len(values) == 0:
 | 
			
		||||
            return []
 | 
			
		||||
        result = [
 | 
			
		||||
            [_("minimum"), min(values)],
 | 
			
		||||
            [_("maximum"), max(values)],
 | 
			
		||||
            [_("mean"), round(mean(values), 2)],
 | 
			
		||||
            [_("median"), median(values)],
 | 
			
		||||
        ]
 | 
			
		||||
        if len(values) > 2:
 | 
			
		||||
            result.append([_("standard deviation"), round(stdev(values), 2)])
 | 
			
		||||
        return result
 | 
			
		||||
        qs = qs.filter(start_day__gte=F("created_date")).annotate(
 | 
			
		||||
            foresight=ExtractDay(F("start_day") - F("created_date"))
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        stats = qs.filter().aggregate(
 | 
			
		||||
            minimum=Min("foresight"),
 | 
			
		||||
            maximum=Max("foresight"),
 | 
			
		||||
            mean=Avg("foresight"),
 | 
			
		||||
            median=Median("foresight"),
 | 
			
		||||
            stdev=StdDev("foresight"),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        statsm = qs.filter(created_date__gte=limit).aggregate(
 | 
			
		||||
            minimum=Min("foresight"),
 | 
			
		||||
            maximum=Max("foresight"),
 | 
			
		||||
            mean=Avg("foresight"),
 | 
			
		||||
            median=Median("foresight"),
 | 
			
		||||
            stdev=StdDev("foresight"),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        return [[_(x), round(stats[x], 2), round(statsm[x], 2)] for x in stats]
 | 
			
		||||
 | 
			
		||||
    def get_global_foresight_quality():
 | 
			
		||||
        return RecurrentImport._get_foresight_quality_internal(Event.objects)
 | 
			
		||||
 | 
			
		||||
    def get_foresight_quality(self):
 | 
			
		||||
        return RecurrentImport._get_foresight_quality_internal(
 | 
			
		||||
            Event.objects.filter(import_sources__contains=[self.source])
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BatchImportation(models.Model):
 | 
			
		||||
 
 | 
			
		||||
@@ -90,7 +90,9 @@
 | 
			
		||||
            <h2>Qualité de l'anticipation</h2>
 | 
			
		||||
            <p>
 | 
			
		||||
              On s'intéresse à la différence entre la date de publication d'un événement et la date effective de l'événement. Plus le nombre de jours qui les sépare est élevé, plus
 | 
			
		||||
              la source anticipe ses événements, et peut être considérée comme une source fiable.
 | 
			
		||||
              la source anticipe ses événements, et peut être considérée comme une source fiable. On ignore les événements ajoutés à l'agenda alors que l'événement a déjà eu lieu.
 | 
			
		||||
              On affiche cette information pour les imports depuis le début de son
 | 
			
		||||
              intégration à l'agenda, mais aussi pour le dernier mois.
 | 
			
		||||
            </p>
 | 
			
		||||
            <table>
 | 
			
		||||
              <thead>
 | 
			
		||||
@@ -99,9 +101,13 @@
 | 
			
		||||
              </thead>
 | 
			
		||||
              <tbody>
 | 
			
		||||
                <tr>
 | 
			
		||||
                  <th class="label">Nb jours</th>
 | 
			
		||||
                  <th class="label">écart (en jours)</th>
 | 
			
		||||
                  {% for v in stat %}<th>{{ v.1 }}</th>{% endfor %}
 | 
			
		||||
                </tr>
 | 
			
		||||
                <tr>
 | 
			
		||||
                  <th class="label">écart du dernier mois (en jours)</th>
 | 
			
		||||
                  {% for v in stat %}<th>{{ v.2 }}</th>{% endfor %}
 | 
			
		||||
                </tr>
 | 
			
		||||
              </tbody>
 | 
			
		||||
            </table>
 | 
			
		||||
          {% endif %}
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,29 @@
 | 
			
		||||
      On retrouve une synthèse par mois du tableau précédent, sous forme d'une moyenne du nombre de création d'événements par jour pour chaque mois.
 | 
			
		||||
    </p>
 | 
			
		||||
    {% include "agenda_culturel/statistics_per_month.html" with data=stats_months_by_creation %}
 | 
			
		||||
    <h2>Qualité de l'anticipation</h2>
 | 
			
		||||
    <p>
 | 
			
		||||
      On s'intéresse à la différence entre la date de publication d'un événement et la date effective de l'événement. Plus le nombre de jours qui les sépare est élevé, plus
 | 
			
		||||
      les sources anticipent leurs événements. On ignore les événements ajoutés à l'agenda alors que l'événement a déjà eu lieu.
 | 
			
		||||
      On affiche cette information pour les imports depuis le début de leur
 | 
			
		||||
      intégration à l'agenda, mais aussi pour le dernier mois.
 | 
			
		||||
    </p>
 | 
			
		||||
    <table>
 | 
			
		||||
      <thead>
 | 
			
		||||
        <th class="label"></th>
 | 
			
		||||
        {% for v in stats_foresight %}<th>{{ v.0 }}</th>{% endfor %}
 | 
			
		||||
      </thead>
 | 
			
		||||
      <tbody>
 | 
			
		||||
        <tr>
 | 
			
		||||
          <th class="label">écart (en jours)</th>
 | 
			
		||||
          {% for v in stats_foresight %}<th>{{ v.1 }}</th>{% endfor %}
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
          <th class="label">écart du dernier mois (en jours)</th>
 | 
			
		||||
          {% for v in stats_foresight %}<th>{{ v.2 }}</th>{% endfor %}
 | 
			
		||||
        </tr>
 | 
			
		||||
      </tbody>
 | 
			
		||||
    </table>
 | 
			
		||||
    <h2>Par ville</h2>
 | 
			
		||||
    <p>Nombre d'événements référencés par ville.</p>
 | 
			
		||||
    <ul>
 | 
			
		||||
 
 | 
			
		||||
@@ -2816,6 +2816,8 @@ def statistics(request):
 | 
			
		||||
        .order_by("-total")
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    stats_foresight = RecurrentImport.get_global_foresight_quality()
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "stats_by_startday": stats["start_day"],
 | 
			
		||||
        "stats_by_creation": stats["created_date__date"],
 | 
			
		||||
@@ -2826,6 +2828,7 @@ def statistics(request):
 | 
			
		||||
        "first_by_creation": first["created_date__date"],
 | 
			
		||||
        "last_by_creation": last["created_date__date"],
 | 
			
		||||
        "nb_by_city": nb_by_city,
 | 
			
		||||
        "stats_foresight": stats_foresight,
 | 
			
		||||
    }
 | 
			
		||||
    return render(request, "agenda_culturel/statistics.html", context)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user