Django QuerySet을 Pandas DataFrame으로 변환


91

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

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

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


안녕하세요 @FrancoMariluis,이 주제에 대해 죄송합니다 : 장고 프로젝트에 판다를 사용하고 계십니까? django 웹 애플리케이션을 통해 "matplotlib로 플로팅"을 사용하여 그래픽을 표시합니다. 당신에게 유효한 솔루션입니까? 감사.
dani herrera

안녕, 장고 나는 그래픽을 보여주는 잘 작동 장고 - chartit을 사용하고 있습니다,하지만 난 나에게 더 많은 유연성을 줄 것이다,하기 matplotlib를 사용하는 방법에 대해 생각하고 있어요
프랑코 Mariluis을

매우 간단 해 보이며 작동합니다. 특별한 문제가 있습니까?
Dmitry Shevchenko

지금 가지고있는 방식에 어떤 문제가 있습니까? 특별한 우려가 있습니까?
Burhan Khalid 2012 년

이것은 저의 첫 번째 (유일한!) 접근 방식 이었지만 판다를 처음 접했기 때문에 다른 방법이 있는지보고 싶었지만 좋은 방법 인 것 같습니다.
Franco Mariluis

답변:


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

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


37
'list ()'사용은 더 이상 사용되지 않는 것 같습니다 (나는 pandas 0.12에 있습니다). 사용하면 DataFrame.from_records()더 잘 작동합니다 df = pd.DataFrame.from_records(BlogPost.objects.all().values()).
gregoltsov

2
이것이 OP 질문의 이름을 사용하면 더 분명해질 것입니다. 예를 들어, BlogPost그의 SomeModel?
Hack-R

안녕하세요, 데이터 프레임에서 필요하지 않은 열을 제외하는 방법이 있습니까?
Willower

19

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)

11
Django Pandas는 대규모 데이터 세트를 어떻게 처리합니까? github.com/chrisdev/django-pandas/blob/master/django_pandas/… 이 줄은 전체 데이터 세트가 한 번에 메모리에로드된다는 것을 의미하기 때문에 나를 두렵게합니다.
Adam Barnes

@Ada 지정된 필드 이름을 사용하여 DataFrame을 만들려면 :df = read_frame(qs, fieldnames=['age', 'wage', 'full_name'])
Gathide

내가 궁금해하는이 놀라운 미래의 여러분을 위해, 그 당시 소스에 대한보다 영구적 인 링크가 있습니다 : github.com/chrisdev/django-pandas/blob/…
Adam Barnes

9

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로 감소했습니다.


2

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


@GregoryGoltsov의 사용 아이디어는 사용 .from_records()하지 않고 list()메모리 효율성 문제를 제거합니다.
hobs

1
메모리 효율성 문제는 Django 측에 있습니다. 결과를 캐시하는를 .values()반환 ValuesQuerySet하므로 충분한 데이터 세트의 경우 메모리 집약적입니다.
David Eyk

1
아, 그래. 당신은 검색어 세트에 인덱스 거라고 사용 .from_records두 메모리 돼지를 제거하기 위해 지능형리스트없이. 예 : pd.DataFrame.from_records(qs[i].__dict__ for i in range(qs.count())). 하지만 "_state"작업 을 마치면 그 성가신 칼럼 이 남습니다 . qs.values()[i]훨씬 빠르고 깨끗하지만 캐시하는 것 같습니다.
hobs

1

아마도 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()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.