DjangoQuerySetをパンダDataFrameに変換する


90

DataFrame次のように、DjangoQuerySetをパンダに変換します。

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

それは機能しますが、より効率的な方法はありますか?


こんにちは@FrancoMariluis、これについてはトピックから外れて申し訳ありません。パンダをdjangoプロジェクトに使用していますか。djangoWebアプリケーションを介して「matplotlibを使用したプロット」を使用してグラフィックを表示します。あなたにとって有効な解決策はありますか?ありがとう。
ダニ・エレーラ

こんにちは、Djangoでグラフィックを表示するために、私はdjango-chartitを使用しています。これは
正常に機能し

非常に簡単に見え、それは機能します。特に懸念はありますか?
Dmitry Shevchenko

あなたが今それを持っている方法の何が問題になっていますか?特に気になることはありますか?
Burhan Khalid

これが私の最初の(そして唯一の!)アプローチでしたが、私はパンダにかなり慣れていないので、別の方法があるかどうかを確認したかったのですが、これは良い方法のようです。
Franco Mariluis 2012

回答:


87
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()'の使用は非推奨になっているようです(私はパンダ0.12を使用しています)。使用DataFrame.from_records()する方がうまくいきdf = pd.DataFrame.from_records(BlogPost.objects.all().values())ます。
gregoltsov 2013年

2
これがOPの質問からの名前を使用した場合、より明確になります。たとえば、BlogPost彼と同じであるはずSomeModelですか?
ハック-R

こんにちは、データフレームで不要な列を除外する方法はありますか?
Willower 2018年

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)

10
Django Pandasは大規模なデータセットをどのように処理しますか? github.com/chrisdev/django-pandas/blob/master/django_pandas/… この行は、データセット全体が一度にメモリにロードされることを意味すると思うので、私を怖がらせます。
アダムバーンズ

@Ada指定されたフィールド名を使用してDataFrameを作成するには:df = read_frame(qs, fieldnames=['age', 'wage', 'full_name'])
Gathide

:私が上だったWTH不思議に思っている。このwonderous将来的にあなたのそれらのために、ここで時のソースに、より恒久的なリンクです github.com/chrisdev/django-pandas/blob/...
アダム・バーンズ

9

values_list()でクエリセットを変換すると、values()で直接変換するよりもメモリ効率が高くなります。メソッドvalues()はdictのリスト(key:valueのペア)のクエリセットを返すため、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"])##機能しません。データ型でクラッシュしたのは、リストではなくクエリセットです。

100万行を超えるデータを使用してプロジェクトでこれをテストしたところ、ピークメモリが2Gから1Gに減少しました。


2

Djangoの観点から(私はよく知らないpandas)、これは問題ありません。私の唯一の懸念は、レコードの数が非常に多い場合、メモリの問題が発生する可能性があることです。この場合、このメモリ効率の高いクエリセットイテレータに沿った何かが必要になります。(書かれたスニペットは、のスマートな使用を可能にするために、いくらかの書き直しが必要な場合があります.values())。


@GregoryGoltsovが使用し.from_records()、使用しないという考えlist()は、メモリ効率の懸念を解消します。
ホブ2014

1
メモリ効率の懸念はDjango側にあります。結果をキャッシュ.values()するaValuesQuerySetを返すため、十分な大きさのデータセットの場合、メモリを大量に消費します。
David Eyk 2014

1
ああ、そうだ。両方のメモリの占有を排除するには、クエリセットにインデックスを付け、リスト内包表記なし使用する.from_records必要があります。例: pd.DataFrame.from_records(qs[i].__dict__ for i in range(qs.count()))。しかし、"_state"完了すると、その厄介な列が残ります。qs.values()[i]はるかに高速でクリーンですが、キャッシュすると思います。
ホブ2014

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.