PYTHONではじめてのWEBサイトを作成 7
さてと
今回は、GooglePlaces APIで取得したバインミーのお店リストをランキングしたいと思います。
Baysian average(ベイズ平均)でランキング
今回はレーティングが高いけどレビュー数が少ない場合にランキングが高くなってしまわないように、レビュー数を考慮してランキングをつけたいと思います。
Baysian average(ベイズ平均)
レーティングとレビュー数の両方を考慮する方法としてベイズ平均を使います。まだバインミーのお店の情報は少ないので加重平均よりベイズ平均の方が良いと思われます。
とりあえずやってみましょう。
平均値の取得:
全体の平均レーティング (C) と平均レビュー数 (m) を計算
ベイズ平均の計算:
各店舗のレーティングとレビュー数に基づいて、加重平均(ベイズ平均)を計算
m はベースラインのレビュー数であり、C は全体の平均レーティング
self.weighted_score は、レビュー数が少ない場合には全体の平均レーティングに近づき、レビュー数が増えると実際のレーティングに近づくように調整されます。
models.py
from django.db import models
class Store(models.Model):
name = models.CharField(max_length=255) # 店名
prefecture = models.CharField(max_length=100) # 都道府県
city = models.CharField(max_length=100) # 市区町村
website = models.URLField(blank=True, null=True)
url = models.URLField() # URL
rating = models.FloatField() # レーティング
review_count = models.IntegerField() # レビュー数
latitude = models.FloatField() # 緯度
longitude = models.FloatField() # 経度
place_id = models.CharField(max_length=255, unique=True) # Google Place ID
weighted_score = models.FloatField(null=True, blank=True) # 加重スコア
def calculate_weighted_score(self):
if self.review_count == 0:
self.weighted_score = 0
return
avg_rating = Store.objects.aggregate(models.Avg('rating'))['rating__avg'] or 0
avg_reviews = Store.objects.aggregate(models.Avg('review_count'))['review_count__avg'] or 0
m = avg_reviews # ベースラインのレビュー数
C = avg_rating # 全体の平均レーティング
self.weighted_score = ((self.review_count / (self.review_count + m)) * self.rating) + ((m / (self.review_count + m)) * C)
def save(self, *args, **kwargs):
self.calculate_weighted_score()
super().save(*args, **kwargs)
マイグレーションします。
python manage.py makemigrations
python manage.py migrate
Baysian average(ベイズ平均)をSQLiteに格納
少しトラブルがありまして、一度全データを消去してから再度Places APIを読み込みましたが、無事にweighted_scoreとして加重スコアが取得できました。
バインミー☆サンドイッチ: Weighted score calculated: 4.3
Store バインミー☆サンドイッチ saved with weighted score: 4.3
Saved store:
バインミーシンチャオ: Weighted score calculated: 4.25819209039548
Store バインミーシンチャオ saved with weighted score: 4.25819209039548
Saved store: バインミーシンチャオ with weighted score: 4.25819209039548
バインミー シンチャオ 浅草店: Weighted score calculated: 4.271109902067464
Store バインミー シンチャオ 浅草店 saved with weighted score: 4.271109902067464
Saved store: バインミー シンチャオ 浅草店 with weighted score: 4.271109902067464
バインミー☆サンドイッチ 水道橋東口店: Weighted score calculated: 4.278412981986006
Store バインミー☆サンドイッチ 水道橋東口店 saved with weighted score: 4.278412981986006
Saved store: バインミー☆サンドイッチ 水道橋東口店 with weighted score: 4.278412981986006
BANH MI NGON NGON TAKADANOBABA: Weighted score calculated: 4.207949225783219
Store BANH MI NGON NGON TAKADANOBABA saved with weighted score: 4.207949225783219
Saved store: BANH MI NGON NGON TAKADANOBABA with weighted score: 4.207949225783219
BANH MI NGON NGON OKUBO(バインミーゴンゴン 大久保店): Weighted score calculated: 4.141688218390805
Store BANH MI NGON NGON OKUBO(バインミーゴンゴン 大久保店) saved with weighted score: 4.141688218390805
Saved store: BANH MI NGON NGON OKUBO(バインミーゴンゴン 大久保店) with weighted score: 4.141688218390805
バインミーサンドイッチ神保町店: Weighted score calculated: 4.222949032433905
Store バインミーサンドイッチ神保町店 saved with weighted score: 4.222949032433905
Saved store: バインミーサンドイッチ神保町店 with weighted score: 4.222949032433905
バインミー☆サンドイッチ: Weighted score calculated: 4.233362910381544
Store バインミー☆サンドイッチ saved with weighted score: 4.233362910381544
Stores in Tokyo fetched and saved successfully.
これを見ると加重スコアに同じ値があるので、加重スコア順が同じ値の場合はレビュー数が多い順にしたいと思います。
まとめ
今回は、お店のレビュー数とレーティングからBaysian average(ベイズ平均)を算出して加重スコアとしました。
加重スコアをmodelsで定義してお店のフィールドに加重スコアをDBに格納しました。
次回はランキングをHTMLで表示したいと思います。
スピード上げないと今月中に間に合わないなー
楽しみながら進めます!