yiskw note

機械学習やプログラミングについて気まぐれで書きます

Djangoでフィールド間の大小比較や差の絶対値の計算を行う


概要

Djangoでフィールド間の大小比較をした結果や,フィールド間の差の絶対値を新しいフィールドとして保存する方法について調べたので,メモを残しておきます.

使用環境

使用するモデル

今回は以下のような対戦結果を保持するモデルを使用します.

from django.db import models


class Matchup(models.Model):
    win_player_id = models.IntegerField()
    win_player_rate = models.IntegerField()

    lose_player_id = models.IntegerField()
    lose_player_rate = models.IntegerField()

方法

新たなフィールドを追加する方法

QuerySetオブジェクトのannotateメソッドを用いることで,新たなフィールドを追加(アノテーション)することができます.
このannotateメソッドは,データの個数のカウントなどによく用いられます.

使用例

# Each publisher, each with a count of books as a "num_books" attribute.
>>> from django.db.models import Count
>>> pubs = Publisher.objects.annotate(num_books=Count('book'))
>>> pubs
<QuerySet [<Publisher: BaloneyPress>, <Publisher: SalamiPress>, ...]>
>>> pubs[0].num_books
73

参照: Aggregation | Django documentation | Django

大小比較した結果を新たなフィールドとして追加する

上で説明したannotateメソッドと,Djangoで定義されているデータベース関数のうちの一つであるSignを用いることで,大小比較をした結果をフィールドに追加することが可能です.

from django.db.models import F
from django.db.models.functions import Sign


# どちらのレートが大きいかを算出.
# +1 -> win_playerの方が大きい.-1 -> lose_playerの方が小さい.
# 0 -> レートが同じ
matchup = Matchup.objects.all().annotate(
    superior=Sign(F("win_player_rate") - F("lose_player_rate"))
)

このFオブジェクトは,モデルの特定のフィールドの値を表現するものです.
上の場合だとwin_player_rateとlose_player_rateの値の差を計算し,その結果に対して正負を求めることで大小関係を取得しています.

フィールド間の差の絶対値を計算し,新たなフィールドとして追加する

こちらも同様にannotateメソッドを使用します.
Djangoでは絶対値を計算するデータベース関数としてAbsが定義されています.

from django.db.models import F
from django.db.models.functions import Abs


matchup = Matchup.objects.all().annotate(
    rate_diff=Abs(F("win_player_rate") - F("lose_player_rate"))
)

まとめ

QeurySetオブジェクトのannotateメソッドと,Djangoで提供されているデータベース関数を用いることで,フィールド間の大小比較や差の絶対値の計算を行うことができました.他にも色々なデータベース関数が定義されているので,様々な処理ができそうです.

参考