Ací es mostren les diferències entre la revisió seleccionada i la versió actual de la pàgina.
| Ambdós costats versió prèvia Revisió prèvia Següent revisió | Revisió prèvia | ||
|
opendata_pandas [2023/07/04 22:16] 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 | + | * 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 |
| * 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' | ||
| - | |||
| ======= 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:// | https:// | ||
| - | JuPyTeR (Julia, Python i R) Notebook és un servei que permet executar codi i llibreries Python al navegador o | + | [[https:// |
| - | en qualsevol IDE, fins i tot llibreries per generar gràfics. | + | en qualsevol IDE, fins i tot llibreries per generar gràfics. |
| **Pas 1. Seleccionar la font de dades.** | **Pas 1. Seleccionar la font de dades.** | ||
| En el nostre cas, dins de la pàgina indicada la taula que ens interessa té un atribut HTML " | En el nostre cas, dins de la pàgina indicada la taula que ens interessa té un atribut HTML " | ||
| - | valor " | + | valor " |
| + | El mètode read_html ha de conèixer la pàgina i atributs html per identificar la taula | ||
| que volem extreure. | que volem extreure. | ||
| **Pas 2. Obtenir les dades amb Pandas** | **Pas 2. Obtenir les dades amb Pandas** | ||
| - | < | + | < |
| import pandas as pd | import pandas as pd | ||
| from io import StringIO | from io import StringIO | ||
| Línia 81: | Línia 82: | ||
| **Pas 3. Filtrar dades i obtenir resultats.** | **Pas 3. Filtrar dades i obtenir resultats.** | ||
| - | < | + | < |
| # Seleccionem la llista dels noms dels equips. | # Seleccionem la llista dels noms dels equips. | ||
| classificacio_df[' | classificacio_df[' | ||
| Línia 98: | Línia 99: | ||
| - | ======= | + | ======= |
| - | Pas 4. Inserim el codi que hem comprovat a la aplicació django, dins de l' | + | **Pas 4. Inserim el codi que hem comprovat a la aplicació django, dins de l' |
| - | Hem de substuïr aquest | + | En primer lloc, posem el codi que hem provat abans: |
| - | < | + | < |
| + | def handle(self, | ||
| + | print(" | ||
| + | # https:// | ||
| + | # Web scrapping: obtenció de dades externes al nostre sistema. | ||
| + | url: str = " | ||
| + | classif: pd.DataFrame = pd.read_html(url, | ||
| + | # Per algún motiu que desconec la informació que m' | ||
| + | # la primera posició d'una llista. | ||
| + | classificacio_df = classif[0] | ||
| + | # Seleccionem la llista dels noms dels equips. | ||
| + | classificacio_df[' | ||
| + | list_aux = classificacio_df[' | ||
| + | llista_equips = sum(list_aux, | ||
| + | print(llista_equips) | ||
| + | print(" | ||
| + | |||
| + | # | ||
| + | titol_lliga = options[' | ||
| + | ... | ||
| </ | </ | ||
| - | Per aquest | + | Després del codi que crea la lliga si no existeix, comento el codi de creació d' |
| + | i poso aquest, que crea i guarda els equips pel seu nom: | ||
| + | |||
| + | <code python> | ||
| + | for nom_equip in llista_equips: | ||
| + | equip = Equip(nom=nom_equip) | ||
| + | # | ||
| + | equip.save() | ||
| + | lliga.equips.add(equip) | ||
| + | |||
| + | # Seleccionarem algunes jugadores. | ||
| + | print(" | ||
| + | ... | ||
| + | </ | ||
| + | |||
| + | |||
| + | --> Codi complet del seeder i el model # | ||
| + | Aquí podreu veure un exemple del codi de l' | ||
| + | |||
| + | <file python / | ||
| + | from django.db import models | ||
| + | |||
| + | # Observació: | ||
| + | # 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, | ||
| + | estadi = models.CharField(max_length=100, | ||
| + | #lliga = models.ForeignKey(Lliga, | ||
| + | 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 = ' | ||
| + | |||
| + | |||
| + | class Jugadora(models.Model): | ||
| + | nom = models.CharField(max_length=100) | ||
| + | cognom = models.CharField(max_length=100) | ||
| + | dorsal = models.IntegerField() | ||
| + | equip = models.ForeignKey(Equip, | ||
| + | |||
| + | def __str__(self): | ||
| + | return f' | ||
| + | class Meta: | ||
| + | verbose_name_plural = ' | ||
| + | |||
| + | |||
| + | class Partit(models.Model): | ||
| + | class Meta: | ||
| + | unique_together = [" | ||
| + | local = models.ForeignKey(Equip, | ||
| + | related_name=" | ||
| + | visitant = models.ForeignKey(Equip, | ||
| + | related_name=" | ||
| + | lliga = models.ForeignKey(Lliga, | ||
| + | detalls = models.TextField(null=True, | ||
| + | inici = models.DateTimeField(null=True, | ||
| + | def __str__(self): | ||
| + | return "{} - {}" | ||
| + | def gols_local(self): | ||
| + | return self.event_set.filter( | ||
| + | tipus=Event.EventType.GOL, | ||
| + | def gols_visitant(self): | ||
| + | return self.event_set.filter( | ||
| + | tipus=Event.EventType.GOL, | ||
| + | |||
| + | |||
| + | class Event(models.Model): | ||
| + | # Solució subòptima i provisional. | ||
| + | # tipus_event = models.CharField(max_length=100) | ||
| + | # el tipus d' | ||
| + | class EventType(models.TextChoices): | ||
| + | GOL = " | ||
| + | AUTOGOL = " | ||
| + | FALTA = " | ||
| + | PENALTY = " | ||
| + | MANS = " | ||
| + | CESSIO = " | ||
| + | FORA_DE_JOC = " | ||
| + | ASSISTENCIA = " | ||
| + | TARGETA_GROGA = " | ||
| + | TARGETA_VERMELLA = " | ||
| + | partit = models.ForeignKey(Partit, | ||
| + | temps = models.TimeField() | ||
| + | tipus = models.CharField(max_length=30, | ||
| + | jugador = models.ForeignKey(Jugadora, | ||
| + | on_delete=models.SET_NULL, | ||
| + | related_name=" | ||
| + | equip = models.ForeignKey(Equip, | ||
| + | on_delete=models.SET_NULL) | ||
| + | # per les faltes | ||
| + | jugador2 = models.ForeignKey(Jugadora, | ||
| + | on_delete=models.SET_NULL, | ||
| + | related_name=" | ||
| + | detalls = models.TextField(null=True, | ||
| + | def __str__(self): | ||
| + | return f' | ||
| + | </ | ||
| + | |||
| + | |||
| + | <file python models.py> | ||
| + | from django.db import models | ||
| + | |||
| + | # Observació: | ||
| + | # 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, | ||
| + | estadi = models.CharField(max_length=100, | ||
| + | #lliga = models.ForeignKey(Lliga, | ||
| + | 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 = ' | ||
| + | |||
| + | |||
| + | class Jugadora(models.Model): | ||
| + | nom = models.CharField(max_length=100) | ||
| + | cognom = models.CharField(max_length=100) | ||
| + | dorsal = models.IntegerField() | ||
| + | equip = models.ForeignKey(Equip, | ||
| + | |||
| + | def __str__(self): | ||
| + | return f' | ||
| + | class Meta: | ||
| + | verbose_name_plural = ' | ||
| + | |||
| + | |||
| + | class Partit(models.Model): | ||
| + | class Meta: | ||
| + | unique_together = [" | ||
| + | local = models.ForeignKey(Equip, | ||
| + | related_name=" | ||
| + | visitant = models.ForeignKey(Equip, | ||
| + | related_name=" | ||
| + | lliga = models.ForeignKey(Lliga, | ||
| + | detalls = models.TextField(null=True, | ||
| + | inici = models.DateTimeField(null=True, | ||
| + | def __str__(self): | ||
| + | return "{} - {}" | ||
| + | def gols_local(self): | ||
| + | return self.event_set.filter( | ||
| + | tipus=Event.EventType.GOL, | ||
| + | def gols_visitant(self): | ||
| + | return self.event_set.filter( | ||
| + | tipus=Event.EventType.GOL, | ||
| + | |||
| + | |||
| + | class Event(models.Model): | ||
| + | # Solució subòptima i provisional. | ||
| + | # tipus_event = models.CharField(max_length=100) | ||
| + | # el tipus d' | ||
| + | class EventType(models.TextChoices): | ||
| + | GOL = " | ||
| + | AUTOGOL = " | ||
| + | FALTA = " | ||
| + | PENALTY = " | ||
| + | MANS = " | ||
| + | CESSIO = " | ||
| + | FORA_DE_JOC = " | ||
| + | ASSISTENCIA = " | ||
| + | TARGETA_GROGA = " | ||
| + | TARGETA_VERMELLA = " | ||
| + | partit = models.ForeignKey(Partit, | ||
| + | temps = models.TimeField() | ||
| + | tipus = models.CharField(max_length=30, | ||
| + | jugador = models.ForeignKey(Jugadora, | ||
| + | on_delete=models.SET_NULL, | ||
| + | related_name=" | ||
| + | equip = models.ForeignKey(Equip, | ||
| + | on_delete=models.SET_NULL) | ||
| + | # per les faltes | ||
| + | jugador2 = models.ForeignKey(Jugadora, | ||
| + | on_delete=models.SET_NULL, | ||
| + | related_name=" | ||
| + | detalls = models.TextField(null=True, | ||
| + | def __str__(self): | ||
| + | return f' | ||
| + | </ | ||
| + | |||
| + | <-- | ||
| + | |||
| + | Resultat final, quan arrenquem la aplicació: | ||
| + | |||
| + | Si heu canviat el model, primer executeu: | ||
| < | < | ||
| + | (env) nomusuari@linux: | ||
| + | (env) nomusuari@linux: | ||
| + | </ | ||
| + | Per omplir les dades de l' | ||
| + | |||
| + | < | ||
| + | (env) nomusuari@linux: | ||
| + | (env) nomusuari@linux: | ||
| + | (env) nomusuari@linux: | ||
| </ | </ | ||
| + | |||
| + | Si anem a veure la taula de partits podem comprovar que s'han generat correctament, | ||
| + | dels locals i visitants. | ||
| + | |||
| + | {{: | ||
| ======= Conclusions ======= | ======= Conclusions ======= | ||
| - | Més info pendent. | + | Publicar i fer ús de dades públiques d' |