Django QuerySet'i Pandalar DataFrame'e dönüştürme


93

Bir Django QuerySet'i pandalara DataFrameşu şekilde dönüştüreceğim:

qs = SomeModel.objects.select_related().filter(date__year=2012)
q = qs.values('date', 'OtherField')
df = pd.DataFrame.from_records(q)

Çalışıyor, ancak daha verimli bir yol var mı?


Merhaba @FrancoMariluis, bunun için özür dilerim konu dışı: django projelerinde pandaları kullanıyor musunuz? Django web uygulamaları aracılığıyla "Matplotlib ile çizim" kullanarak grafikleri gösterirsiniz. Sizin için geçerli bir çözüm mü? Teşekkürler.
dani herrera

Merhaba, Django'da grafikleri göstermek için iyi çalışan django-chartit kullanıyorum, ancak matplotlib kullanmayı düşünüyorum, bu da bana daha fazla esneklik sağlayacak
Franco Mariluis

Oldukça basit görünüyor ve işe yarıyor. Herhangi bir özel endişeniz var mı?
Dmitry Shevchenko

Şimdi elde etme şeklinin nesi var? Özel bir endişeniz mi var?
Burhan Khalid

Bu benim ilk (ve tek!) Yaklaşımımdı, ancak pandalarda oldukça yeni olduğum için başka bir yol olup olmadığını görmek istedim, ancak bu iyi bir yol gibi görünüyor.
Franco Mariluis

Yanıtlar:


90
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')))

Yukarıdakiler aynı şeyi nasıl yaptığım. En kullanışlı ek, hangi alanlarla ilgilendiğinizi belirlemektir. İlgilendiğiniz mevcut alanların yalnızca bir alt kümesiyse, bu, tahmin ettiğim gibi bir performans artışı sağlar.


38
'List ()' kullanımı kullanımdan kaldırılmış gibi görünüyor (Pandalar 0.12'deyim). Kullanmak DataFrame.from_records()daha iyi çalışır, yani df = pd.DataFrame.from_records(BlogPost.objects.all().values()).
gregoltsov

2
Bunun OP sorusundaki isimleri kullanması daha açık olacaktır. Örneğin, BlogPostonunkiyle aynı mı olmalı SomeModel?
Hack-R

Merhaba, veri çerçevesinde ihtiyacınız olmayan bir sütunu hariç tutmanın bir yolu var mı?
Willower

19

Django Pandas bunu oldukça düzgün bir şekilde çözer: https://github.com/chrisdev/django-pandas/

BENİOKU'dan:

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)

11
Django Pandalar büyük veri kümeleriyle nasıl başa çıkıyor? github.com/chrisdev/django-pandas/blob/master/django_pandas/… Bu satır beni korkutuyor, çünkü bence tüm veri setinin aynı anda belleğe yükleneceği anlamına geliyor.
Adam Barnes

@Ada Belirtilen alan adlarını kullanarak bir DataFrame oluşturmak için:df = read_frame(qs, fieldnames=['age', 'wage', 'full_name'])
Gathide

Bu harikulade gelecekte neler olup bittiğini merak edenler için, işte o zamanki kaynağa daha kalıcı bir bağlantı: github.com/chrisdev/django-pandas/blob/…
Adam Barnes

10

Sorgu kümesini values_list () üzerinde dönüştürmek, doğrudan values ​​() 'dan daha fazla bellek açısından verimli olacaktır. Yöntem values ​​(), dikte listesinin bir sorgu kümesini (anahtar: değer çiftleri) döndürdüğünden, values_list () yalnızca tuple listesini (saf veri) döndürür. Yaklaşık% 50 bellek tasarrufu sağlar, sadece pd.DataFrame () 'i çağırdığınızda sütun bilgilerini ayarlamanız yeterlidir.

Yöntem 1:
    queryset = models.xxx.objects.values ​​("A", "B", "C", "D")
    df = pd.DataFrame (list (sorgu kümesi)) ## çok fazla bellek tüketir
    #df = pd.DataFrame.from_records (sorgu kümesi) ## çalışıyor ancak bellek kullanımında fazla değişiklik yok

Yöntem 2:
    queryset = models.xxx.objects.values_list ("A", "B", "C", "D")
    df = pd.DataFrame (liste (sorgu kümesi), sütunlar = ["A", "B", "C", "D"]) ## bu% 50 bellek tasarrufu sağlar
    #df = pd.DataFrame.from_records (sorgu kümesi, sütunlar = ["A", "B", "C", "D"]) ## Çalışmıyor. Veri türü ile çöktü sorgu kümesi değil liste.

Bunu projemde> 1 milyon satır verisi ile test ettim, tepe bellek 2G'den 1G'ye düşürüldü.


2

Django perspektifinden (aşina değilim pandas) bu sorun değil. Tek endişem, çok sayıda kaydınız varsa, hafıza sorunlarıyla karşılaşabileceğinizdir. Durum böyle olsaydı, bu bellek verimli sorgu kümesi yineleyicisinin satırları boyunca bir şey gerekli olurdu. (Yazılan pasaj, akıllıca kullanımınıza izin vermek için biraz yeniden yazmayı gerektirebilir .values()).


@ GregoryGoltsov'un kullanma .from_records()ve kullanmama fikri list(), bellek verimliliği endişesini ortadan kaldıracaktır.
ocak

1
Bellek verimliliği endişesi Django tarafındadır. sonuçları önbelleğe alan .values()bir döndürür ValuesQuerySet, bu nedenle yeterince büyük bir veri kümesi için oldukça bellek yoğun olacaktır.
David Eyk

1
Ahh evet. Sen sorgu kümesi içine endeksi olurdu ve kullanmak .from_recordshem hafıza domuz ortadan kaldırmak için liste anlama olmadan. ör pd.DataFrame.from_records(qs[i].__dict__ for i in range(qs.count())). Ama "_state"işin bittiğinde o sinir bozucu sütunla baş başa kalırsın. qs.values()[i]çok daha hızlı ve daha temiz, ancak önbelleğe alındığını düşünüyorum.
Ocak

1

Model_to_dict kullanabilirsiniz

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()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.