ฉันจะแปลง Django QuerySet เป็นแพนด้าDataFrame
ดังนี้:
qs = SomeModel.objects.select_related().filter(date__year=2012)
q = qs.values('date', 'OtherField')
df = pd.DataFrame.from_records(q)
ได้ผล แต่มีวิธีที่มีประสิทธิภาพมากกว่านี้หรือไม่?
ฉันจะแปลง Django QuerySet เป็นแพนด้าDataFrame
ดังนี้:
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')))
ข้างต้นเป็นวิธีที่ฉันทำสิ่งเดียวกัน การเพิ่มที่มีประโยชน์ที่สุดคือการระบุสาขาที่คุณสนใจหากเป็นเพียงส่วนย่อยของฟิลด์ที่มีอยู่ที่คุณสนใจสิ่งนี้จะช่วยเพิ่มประสิทธิภาพอย่างที่ฉันคิด
DataFrame.from_records()
df = pd.DataFrame.from_records(BlogPost.objects.all().values())
BlogPost
ควรจะเหมือนกับของเขาSomeModel
หรือไม่?
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)
df = read_frame(qs, fieldnames=['age', 'wage', 'full_name'])
การแปลง queryset บน values_list () จะทำให้หน่วยความจำมีประสิทธิภาพมากกว่าค่า () โดยตรง เนื่องจาก method 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), column = ["A", "B", "C", "D"]) ## ซึ่งจะช่วยประหยัดหน่วยความจำ 50% #df = pd.DataFrame.from_records (queryset, column = ["A", "B", "C", "D"]) ## ไม่ทำงาน Crashed with datatype is queryset not list.
ฉันทดสอบสิ่งนี้ในโครงการของฉันด้วยข้อมูล> 1 ล้านแถวหน่วยความจำสูงสุดจะลดลงจาก 2G เป็น 1G
จากมุมมองของ Django (ฉันไม่คุ้นเคยpandas
) ก็ใช้ได้ สิ่งเดียวที่ฉันกังวลคือถ้าคุณมีบันทึกจำนวนมากคุณอาจประสบปัญหาเกี่ยวกับหน่วยความจำ หากเป็นกรณีนี้จำเป็นต้องมีบางสิ่งบางอย่างตามบรรทัดของตัววนซ้ำแบบสอบถามที่มีประสิทธิภาพของหน่วยความจำนี้ (ตัวอย่างข้อมูลตามที่เขียนอาจต้องมีการเขียนใหม่เพื่อให้สามารถใช้งานได้อย่างชาญฉลาด.values()
)
.from_records()
และไม่ใช้list()
จะช่วยขจัดปัญหาด้านประสิทธิภาพของหน่วยความจำ
.from_records
โดยไม่มีความเข้าใจในรายการเพื่อกำจัดหมูหน่วยความจำทั้งสอง เช่น pd.DataFrame.from_records(qs[i].__dict__ for i in range(qs.count()))
. แต่คุณจะเหลือ"_state"
คอลัมน์ที่น่ารำคาญเมื่อคุณทำเสร็จแล้ว qs.values()[i]
เร็วและสะอาดกว่ามาก แต่ฉันคิดว่ามันแคช
คุณอาจใช้ 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()