Django QuerySet을 Pandas DataFrame으로 변환 pandas 로

DataFrame다음과 같이 Django QuerySet을 pandas 로 변환 합니다.

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

작동하지만 더 효율적인 방법이 있습니까?



답변

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

위는 동일한 작업을 수행하는 방법입니다. 가장 유용한 추가 기능은 관심있는 필드를 지정하는 것입니다. 관심이있는 사용 가능한 필드의 하위 집합 만 있으면 성능이 향상 될 것입니다.


답변

Django Pandas는이 문제를 깔끔하게 해결합니다. https://github.com/chrisdev/django-pandas/

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)

답변

values_list ()에 대한 쿼리 세트를 변환하면 values ​​() 직접보다 메모리가 더 효율적입니다. values ​​() 메서드는 dict 목록 (키 : 값 쌍)의 쿼리 집합을 반환하므로 values_list ()는 튜플 목록 (순수 데이터) 만 반환합니다. 약 50 %의 메모리를 절약 할 수 있으며 pd.DataFrame ()을 호출 할 때 열 정보를 설정하기 만하면됩니다.

방법 1 :
    queryset = models.xxx.objects.values ​​( "A", "B", "C", "D")
    df = pd.DataFrame (list (queryset)) ## 많은 메모리 소모
    #df = pd.DataFrame.from_records (queryset) ## 작동하지만 메모리 사용량에 큰 변화는 없습니다.

방법 2 :
    queryset = models.xxx.objects.values_list ( "A", "B", "C", "D")
    df = pd.DataFrame (list (queryset), columns = [ "A", "B", "C", "D"]) ## 50 % 메모리 절약
    #df = pd.DataFrame.from_records (queryset, columns = [ "A", "B", "C", "D"]) ## 작동하지 않습니다. 데이터 유형이 목록이 아닌 쿼리 세트와 충돌했습니다.

1 백만 행 이상의 데이터로 프로젝트에서 이것을 테스트했는데 최대 메모리가 2G에서 1G로 감소했습니다.


답변

Django 관점에서 (저는 익숙하지 않습니다 pandas) 이것은 괜찮습니다. 내 유일한 관심사는 레코드 수가 매우 많으면 메모리 문제가 발생할 수 있다는 것입니다. 이것이 사실이라면이 메모리 효율적인 쿼리 세트 반복자 의 라인을 따라 무언가 가 필요할 것입니다. (작성된 스 니펫은을 현명하게 사용하기 위해 약간의 재 작성이 필요할 수 있습니다 .values().)


답변

아마도 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()