Je vais convertir un Django QuerySet en pandas DataFrame
comme suit:
qs = SomeModel.objects.select_related().filter(date__year=2012)
q = qs.values('date', 'OtherField')
df = pd.DataFrame.from_records(q)
Cela fonctionne, mais y a-t-il un moyen plus efficace?
Réponses:
import pandas as pd import datetime from myapp.models import BlogPost df = pd.DataFrame(list(BlogPost.objects.all().values())) df = pd.DataFrame(list(BlogPost.objects.filter(date__gte=datetime.datetime(2012, 5, 1)).values())) # limit which fields df = pd.DataFrame(list(BlogPost.objects.all().values('author', 'date', 'slug')))
Voici comment je fais la même chose. L'ajout le plus utile est de spécifier les champs qui vous intéressent. Si ce n'est qu'un sous-ensemble des champs disponibles qui vous intéresse, cela donnerait une amélioration des performances, j'imagine.
la source
DataFrame.from_records()
fonctionne mieux, c'est à diredf = pd.DataFrame.from_records(BlogPost.objects.all().values())
.BlogPost
censé être le même que le sienSomeModel
?Django Pandas résout cela plutôt proprement: https://github.com/chrisdev/django-pandas/
Depuis le README:
class MyModel(models.Model): full_name = models.CharField(max_length=25) age = models.IntegerField() department = models.CharField(max_length=3) wage = models.FloatField() from django_pandas.io import read_frame qs = MyModel.objects.all() df = read_frame(qs)
la source
df = read_frame(qs, fieldnames=['age', 'wage', 'full_name'])
Convertir le jeu de requêtes sur values_list () sera plus efficace en mémoire que sur values () directement. Puisque la méthode values () renvoie un ensemble de requêtes de liste de dict (paires clé: valeur), values_list () renvoie uniquement la liste de tuple (données pures). Cela économisera environ 50% de mémoire, il suffit de définir les informations de la colonne lorsque vous appelez pd.DataFrame ().
J'ai testé cela sur mon projet avec> 1 million de données de lignes, la mémoire de pointe est réduite de 2G à 1G.
la source
Du point de vue de Django (je ne suis pas familier avec
pandas
) c'est très bien. Ma seule préoccupation est que si vous avez un très grand nombre d'enregistrements, vous risquez de rencontrer des problèmes de mémoire. Si tel était le cas, quelque chose du genre de cet itérateur de jeu de requêtes efficace en mémoire serait nécessaire. (L'extrait tel qu'il est écrit peut nécessiter une réécriture pour permettre votre utilisation intelligente de.values()
).la source
.from_records()
et de ne pas utiliserlist()
éliminera le problème d'efficacité de la mémoire..values()
renvoie unValuesQuerySet
qui met en cache les résultats, donc pour un ensemble de données assez grand, cela va être assez gourmand en mémoire..from_records
sans la compréhension de la liste pour éliminer les deux problèmes de mémoire. par exemplepd.DataFrame.from_records(qs[i].__dict__ for i in range(qs.count()))
. Mais vous vous retrouvez avec cette"_state"
colonne ennuyeuse lorsque vous avez terminé.qs.values()[i]
est beaucoup plus rapide et plus propre, mais je pense qu'il met en cache.Vous pouvez peut-être utiliser model_to_dict
import datetime from django.forms import model_to_dict pallobjs = [ model_to_dict(pallobj) for pallobj in PalletsManag.objects.filter(estado='APTO_PARA_VENTA')] df = pd.DataFrame(pallobjs) df.head()
la source