2012-07-28 3 views
45

Tôi sẽ chuyển đổi một Django QuerySet để một gấu trúc DataFrame như sau:Chuyển đổi Django QuerySet để gấu trúc DataFrame

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

Nó hoạt động, nhưng là có một cách hiệu quả hơn?

+0

Hi @FrancoMariluis, xin lỗi về vấn đề này ra khỏi chủ đề: là bạn sử dụng gấu trúc vào các dự án django. Bạn hiển thị đồ họa bằng cách sử dụng "Vẽ bằng matplotlib" thông qua các ứng dụng web django. Là một giải pháp hợp lệ cho bạn? Cảm ơn. – danihp

+0

Xin chào, để hiển thị đồ họa ở Django tôi đang sử dụng django-chartit, hoạt động tốt, nhưng tôi đang nghĩ đến việc sử dụng matplotlib, điều này sẽ giúp tôi linh hoạt hơn –

+0

trông giống như một cách hay. –

Trả lời

2

Từ góc độ Django (Tôi không quen với pandas) điều này là tốt. Mối quan tâm duy nhất của tôi là nếu bạn có số lượng bản ghi rất lớn, bạn có thể gặp phải vấn đề về bộ nhớ. Nếu trường hợp này xảy ra, điều gì đó dọc theo các dòng của memory efficient queryset iterator này là cần thiết. (Đoạn mã được viết có thể yêu cầu viết lại để cho phép sử dụng thông minh .values()) của bạn.

+0

@ GregoryGoltsov để sử dụng '.from_records()' và không sử dụng 'list()' sẽ loại bỏ mối quan tâm về hiệu quả bộ nhớ. – hobs

+1

Mối quan tâm về hiệu quả bộ nhớ là ở phía Django. ['.values ​​()'] (https://docs.djangoproject.com/en/1.7/ref/models/querysets/#django.db.models.query.QuerySet.values) trả về một 'ValuesQuerySet' để lưu trữ kết quả , do đó, đối với một tập dữ liệu đủ lớn, nó sẽ có khá nhiều bộ nhớ. –

+0

Ahh có. Bạn sẽ phải lập chỉ mục vào queryset * và * sử dụng '.from_records' mà không có danh sách hiểu để loại bỏ cả hai bộ nhớ. ví dụ. 'pd.DataFrame.from_records (qs [i] .__ dict__ cho i trong phạm vi (qs.count()))'. Nhưng bạn còn lại với cột '" _state "khó chịu đó khi bạn hoàn thành. 'qs.values ​​() [i]' là nhanh hơn và sạch hơn, nhưng tôi nghĩ rằng nó lưu trữ. – hobs

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

Ở trên là cách tôi làm điều tương tự. Việc bổ sung hữu ích nhất là xác định các trường mà bạn quan tâm. Nếu nó chỉ là một tập hợp con của các trường có sẵn mà bạn quan tâm, thì điều này sẽ làm tăng hiệu năng tôi tưởng tượng.

+16

Sử dụng 'list()' dường như không còn được dùng nữa (tôi đang ở trên gấu trúc 0,12). Sử dụng 'DataFrame.from_records()' hoạt động tốt hơn, tức là 'df = pd.DataFrame.from_records (BlogPost.objects.all(). Values ​​())'. – gregoltsov

+0

Sẽ rõ ràng hơn nếu điều này sử dụng tên từ câu hỏi OP. Ví dụ, 'BlogPost' được cho là giống với' SomeModel' của anh ta? –

0

Bạn có thể có thể sử dụng 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() 
9

Django Pandas giải quyết này khá gọn gàng: https://github.com/chrisdev/django-pandas/

Từ 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) 
+2

Django Pandas đối phó với các tập dữ liệu lớn như thế nào? https://github.com/chrisdev/django-pandas/blob/master/django_pandas/io.py#L107 Dòng này làm tôi sợ, bởi vì tôi nghĩ nó có nghĩa là toàn bộ tập dữ liệu sẽ được tải vào bộ nhớ cùng một lúc. –