bytes.cat

La wiki d'FP d'informàtica

Eines de l'usuari

Eines del lloc


opendata_pandas

Diferències

Ací es mostren les diferències entre la revisió seleccionada i la versió actual de la pàgina.

Enllaç a la visualització de la comparació

Ambdós costats versió prèvia Revisió prèvia
Següent revisió
Revisió prèvia
opendata_pandas [2023/07/04 22:54]
miquel_angel_amoros [Exemple codi local]
opendata_pandas [2023/07/04 23:23] (actual)
miquel_angel_amoros [Per què triem Pandas ?]
Línia 18: Línia 18:
 ======= Per què triem Pandas ? ======= ======= Per què triem Pandas ? =======
  
-  * Ens proporciona una col·lecció molt útil, inexistent a Python, el DataFrame. És una taula bidimensional que podem indexar amb la/les columna/es que més ens interessin en cada monment (com a SQL).+  * Ens proporciona una col·lecció molt útil, inexistent a Python, el DataFrame. És una taula bidimensional que podem indexar amb la/les columna/es que més ens interessin en cada moment (com a SQL).
   * Pandas detecta automàticament inconsistències de tipus i contingut en les dades. Aconseguim avantatges similars als llenguatges de tipat fort (C, Java).   * Pandas detecta automàticament inconsistències de tipus i contingut en les dades. Aconseguim avantatges similars als llenguatges de tipat fort (C, Java).
   * Ens permet tractar grans volums de dades (superiors a 10.000 lines) amb molts mètodes per filtrar la informació.   * Ens permet tractar grans volums de dades (superiors a 10.000 lines) amb molts mètodes per filtrar la informació.
Línia 24: Línia 24:
   * Si organitzem les dades del Dataframe convenientment podem crear gràfics amb llibreries com Matplotlib o Seaborn, amb menys codi que si el posessim en llistes o diccionaris.   * Si organitzem les dades del Dataframe convenientment podem crear gràfics amb llibreries com Matplotlib o Seaborn, amb menys codi que si el posessim en llistes o diccionaris.
   * També facilita la feina si usem llibreries de Machine Learning.   * També facilita la feina si usem llibreries de Machine Learning.
-  * És una molt bona alternativa al llenguatge R, amb una corba d'aprentatge inferior si tenim coneixements bàsics de Python. 
- 
 ======= Instal·lació llibreria Pandas ======= ======= Instal·lació llibreria Pandas =======
  
Línia 47: Línia 45:
  
 A més a més, ens interessa automatitzar les tasques.  A més a més, ens interessa automatitzar les tasques. 
 +
 +**Exemple codi local, arrencat en un fitxer IPYNB**
  
 El codi que mostro a continuació el podeu veure arrencat en directe a: El codi que mostro a continuació el podeu veure arrencat en directe a:
Línia 52: Línia 52:
 https://colab.research.google.com/drive/1vKHXmy5e9KFGv3EnRHwJpzeHTP5zp6I5#scrollTo=ROmuDJnMryJL https://colab.research.google.com/drive/1vKHXmy5e9KFGv3EnRHwJpzeHTP5zp6I5#scrollTo=ROmuDJnMryJL
  
-JuPyTeR (Julia, Python i R) Notebook és un servei que permet executar codi i llibreries Python al navegador o  +[[https://jupyter.org/try-jupyter/retro/notebooks/?path=notebooks/Intro.ipynb|JuPyTeR (Julia, Python i R) Notebook]] és un servei que permet executar codi i llibreries Python al navegador o  
-en qualsevol IDE, fins i tot llibreries per generar gràfics.    +en qualsevol IDE, fins i tot llibreries per generar gràfics. Els seus fitxers tenen la extensió **.IPYNB**    
  
 **Pas 1. Seleccionar la font de dades.** **Pas 1. Seleccionar la font de dades.**
Línia 101: Línia 101:
 ======= Codi integrat a la aplicació web amb Django ======= ======= Codi integrat a la aplicació web amb Django =======
  
-Pas 4. Inserim el codi que hem comprovat a la aplicació django, dins de l'script seeder.+**Pas 4. Inserim el codi que hem comprovat a la aplicació django, dins de l'script seeder.**
  
 En primer lloc, posem el codi que hem provat abans: En primer lloc, posem el codi que hem provat abans:
Línia 142: Línia 142:
             ...             ...
 </code> </code>
 +
 +
 +--> Codi complet del seeder i el model #
 +Aquí podreu veure un exemple del codi de l'script i també el model.py que s'utilitza. 
 +
 +<file python /management/commands/crea_lliga.py>
 +from django.db import models
 +
 +# Observació: Django genera per defecte camps id autonumèrics
 +# com a clau primària. Hi ha formes de canviar aquest 
 +# comportament però per ara ens sembla OK.
 +
 +# Hauria de posar una relació ManyToMany per tal que un mateix equip
 +# pugui compatir en diverses lligues en un any (Champions)
 +# equips = models.ManyToManyField(Equip)
 +class Equip(models.Model):
 +    nom = models.CharField(max_length=100)
 +    ciutat = models.CharField(max_length=100,null=True)
 +    estadi = models.CharField(max_length=100,null=True)
 +    #lliga = models.ForeignKey(Lliga, on_delete=models.CASCADE)
 +    def __str__(self):
 +        return self.nom
 +
 +
 +class Lliga(models.Model):
 +    nom_temporada = models.CharField(max_length=100)
 +    equips = models.ManyToManyField(Equip)
 +    def __str__(self):
 +        return self.nom_temporada
 +    class Meta:
 +        verbose_name_plural = 'Lligues'
 +
 +
 +class Jugadora(models.Model):
 +    nom = models.CharField(max_length=100)
 +    cognom = models.CharField(max_length=100)
 +    dorsal = models.IntegerField()
 +    equip = models.ForeignKey(Equip, on_delete=models.CASCADE)
 +
 +    def __str__(self):
 +        return f'{self.dorsal} - {self.nom}'
 +    class Meta:
 +        verbose_name_plural = 'Jugadores'
 +
 +
 +class Partit(models.Model):
 +    class Meta:
 +        unique_together = ["local","visitant","lliga"]
 +    local = models.ForeignKey(Equip,on_delete=models.CASCADE,
 +                    related_name="partits_local",null=True,blank=True)
 +    visitant = models.ForeignKey(Equip,on_delete=models.CASCADE,
 +                    related_name="partits_visitant",null=True,blank=True)
 +    lliga = models.ForeignKey(Lliga,on_delete=models.CASCADE)
 +    detalls = models.TextField(null=True,blank=True)
 +    inici = models.DateTimeField(null=True,blank=True)
 +    def __str__(self):
 +        return "{} - {}".format(self.local,self.visitant)
 +    def gols_local(self):
 +        return self.event_set.filter(
 +            tipus=Event.EventType.GOL,equip=self.local).count()
 +    def gols_visitant(self):
 +        return self.event_set.filter(
 +            tipus=Event.EventType.GOL,equip=self.visitant).count()
 +
 +
 +class Event(models.Model):
 +    # Solució subòptima i provisional.
 +    # tipus_event = models.CharField(max_length=100)
 +    # el tipus d'event l'implementem amb algo tipus "enum"
 +    class EventType(models.TextChoices):
 +        GOL = "GOL"
 +        AUTOGOL = "AUTOGOL"
 +        FALTA = "FALTA"
 +        PENALTY = "PENALTY"
 +        MANS = "MANS"
 +        CESSIO = "CESSIO"
 +        FORA_DE_JOC = "FORA_DE_JOC"
 +        ASSISTENCIA = "ASSISTENCIA"
 +        TARGETA_GROGA = "TARGETA_GROGA"
 +        TARGETA_VERMELLA = "TARGETA_VERMELLA"
 +    partit = models.ForeignKey(Partit,on_delete=models.CASCADE)
 +    temps = models.TimeField()
 +    tipus = models.CharField(max_length=30,choices=EventType.choices)
 +    jugador = models.ForeignKey(Jugadora,null=True,
 +                    on_delete=models.SET_NULL,
 +                    related_name="events_fets")
 +    equip = models.ForeignKey(Equip,null=True,
 +                    on_delete=models.SET_NULL)
 +    # per les faltes
 +    jugador2 = models.ForeignKey(Jugadora,null=True,blank=True,
 +                    on_delete=models.SET_NULL,
 +                    related_name="events_rebuts")
 +    detalls = models.TextField(null=True,blank=True)
 +    def __str__(self):
 +        return f'{self.EventType} - {self.jugador}'
 +</file>
 +
 +
 +<file python models.py>
 +from django.db import models
 +
 +# Observació: Django genera per defecte camps id autonumèrics
 +# com a clau primària. Hi ha formes de canviar aquest 
 +# comportament però per ara ens sembla OK.
 +
 +# Hauria de posar una relació ManyToMany per tal que un mateix equip
 +# pugui compatir en diverses lligues en un any (Champions)
 +# equips = models.ManyToManyField(Equip)
 +class Equip(models.Model):
 +    nom = models.CharField(max_length=100)
 +    ciutat = models.CharField(max_length=100,null=True)
 +    estadi = models.CharField(max_length=100,null=True)
 +    #lliga = models.ForeignKey(Lliga, on_delete=models.CASCADE)
 +    def __str__(self):
 +        return self.nom
 +
 +
 +class Lliga(models.Model):
 +    nom_temporada = models.CharField(max_length=100)
 +    equips = models.ManyToManyField(Equip)
 +    def __str__(self):
 +        return self.nom_temporada
 +    class Meta:
 +        verbose_name_plural = 'Lligues'
 +
 +
 +class Jugadora(models.Model):
 +    nom = models.CharField(max_length=100)
 +    cognom = models.CharField(max_length=100)
 +    dorsal = models.IntegerField()
 +    equip = models.ForeignKey(Equip, on_delete=models.CASCADE)
 +
 +    def __str__(self):
 +        return f'{self.dorsal} - {self.nom}'
 +    class Meta:
 +        verbose_name_plural = 'Jugadores'
 +
 +
 +class Partit(models.Model):
 +    class Meta:
 +        unique_together = ["local","visitant","lliga"]
 +    local = models.ForeignKey(Equip,on_delete=models.CASCADE,
 +                    related_name="partits_local",null=True,blank=True)
 +    visitant = models.ForeignKey(Equip,on_delete=models.CASCADE,
 +                    related_name="partits_visitant",null=True,blank=True)
 +    lliga = models.ForeignKey(Lliga,on_delete=models.CASCADE)
 +    detalls = models.TextField(null=True,blank=True)
 +    inici = models.DateTimeField(null=True,blank=True)
 +    def __str__(self):
 +        return "{} - {}".format(self.local,self.visitant)
 +    def gols_local(self):
 +        return self.event_set.filter(
 +            tipus=Event.EventType.GOL,equip=self.local).count()
 +    def gols_visitant(self):
 +        return self.event_set.filter(
 +            tipus=Event.EventType.GOL,equip=self.visitant).count()
 +
 +
 +class Event(models.Model):
 +    # Solució subòptima i provisional.
 +    # tipus_event = models.CharField(max_length=100)
 +    # el tipus d'event l'implementem amb algo tipus "enum"
 +    class EventType(models.TextChoices):
 +        GOL = "GOL"
 +        AUTOGOL = "AUTOGOL"
 +        FALTA = "FALTA"
 +        PENALTY = "PENALTY"
 +        MANS = "MANS"
 +        CESSIO = "CESSIO"
 +        FORA_DE_JOC = "FORA_DE_JOC"
 +        ASSISTENCIA = "ASSISTENCIA"
 +        TARGETA_GROGA = "TARGETA_GROGA"
 +        TARGETA_VERMELLA = "TARGETA_VERMELLA"
 +    partit = models.ForeignKey(Partit,on_delete=models.CASCADE)
 +    temps = models.TimeField()
 +    tipus = models.CharField(max_length=30,choices=EventType.choices)
 +    jugador = models.ForeignKey(Jugadora,null=True,
 +                    on_delete=models.SET_NULL,
 +                    related_name="events_fets")
 +    equip = models.ForeignKey(Equip,null=True,
 +                    on_delete=models.SET_NULL)
 +    # per les faltes
 +    jugador2 = models.ForeignKey(Jugadora,null=True,blank=True,
 +                    on_delete=models.SET_NULL,
 +                    related_name="events_rebuts")
 +    detalls = models.TextField(null=True,blank=True)
 +    def __str__(self):
 +        return f'{self.EventType} - {self.jugador}'
 +</file>
 +
 +<--
 +
 +Resultat final, quan arrenquem la aplicació:
 +
 +Si heu canviat el model, primer executeu:
 +
 +<code>
 +(env) nomusuari@linux:~/lligafemprj$ python manage.py makemigrations lliga
 +(env) nomusuari@linux:~/lligafemprj$ python manage.py migrate
 +</code>
 +
 +Per omplir les dades de l'script seeder:
 +
 +<code>
 +(env) nomusuari@linux:~/lligafemprj$ ./manage.py crea_lliga <nom_lliga>
 +(env) nomusuari@linux:~/lligafemprj$ ./manage.py runserver
 +(env) nomusuari@linux:~/lligafemprj$ firefox http://127.0.0.1:8080/admin
 +</code>
 +
 +Si anem a veure la taula de partits podem comprovar que s'han generat correctament, juntament amb els gols 
 +dels locals i visitants.
 +
 +{{:panell_admin_opendata.jpg?600|}}
  
 ======= Conclusions ======= ======= Conclusions =======
opendata_pandas.1688511255.txt.gz · Darrera modificació: 2023/07/04 22:54 per miquel_angel_amoros