时间序列数据的 Django 数据库结构?

Jon*_*ood 6 python database django django-models pandas

我正在开发一个应用程序,允许用户选择海洋浮标,然后通过交互式绘图探索其历史时间序列数据。我的最终目标是用户可以输入一个位置,然后加载浮标的数据,然后用户可以选择他们想要绘制的数据的过滤器(基本上是仪表板)。例如,也许他们只想查看 8 月份发生的大于 1 英尺的海浪。

我知道如何使用 pandas 和plotly 来做到这一点,但我正在努力解决如何将其转移到 django 数据库框架。

该代码当前创建一个具有数据属性的浮标对象。该数据属性是一个字典,其结构如下:

{'stdmet':{'meta':{dictionary of metadata}, 'data':[pandas dataframe of time series data]}}
Run Code Online (Sandbox Code Playgroud)

我将数据放在 pandas 数据框中,因为它使我可以轻松操作和创建交互式绘图。

我的问题是我应该如何将其保存到 django 模型?我认为我应该有一个浮标类,其中包含元数据字段(例如浮标 ID、纬度/经度等),然后我希望有一个时间序列数据的最终字段。我希望这个字段保留为 2D pandas 数据框。

我发现这种方法令人满意的另一个原因是它不会为每次测量创建一个新的浮标对象。相反,浮标对象将包含其内部所有历史测量值的 2D 数据帧。这看起来更干净。

对此的任何建议将不胜感激!

roo*_*oob 4

这里的标准方法是使用 Django 模型(转换为数据库中的表):

  • Buoy
  • BuoyData

班级BuoyData将有一个ForeignKey模型Buoy

另请参阅GeoDjango用于存储和查询 lat/lngs。您将需要使用PointFieldfrom django.contrib.gis.db.models。以下是一些示例模型:

from django.contrib.gis.db import models


class Buoy(models.Model):
    """
    Represents a Buoy
    """
    location = models.PointField()
    name = models.CharField(max_length=200, null=True, blank=True)


class BuoyData(models.Model):
    """
    Represents a single Buoy datapoint
    """
    buoy = models.ForeignKey(Buoy, related_name='data')
    date = models.DateTimeField()
    # swell size in feet
    swell_size_ft = models.DecimalField(decimal_places=2, max_digits=5)
Run Code Online (Sandbox Code Playgroud)

然后,您可以查询Buoy位于或接近纬度/经度的位置,然后查询 的Buoy数据。

django_pandas包有一个非常有用的方法将 Django 查询集读入 Pandas 数据帧:

from django_pandas.io import read_frame

buoy = Buoy.objects.get(id=10)
data_queryset = buoy.data.all()
df = read_frame(data_queryset)

# or another example
import datetime
from django.utils import timezone
from django.contrib.gis.geos import Point

lat = 36.123
lng = -121.123
# notice how lng is x, lat is y
location = Point(lng, lat)

time_four_days_ago = timezone.now() - datetime.timedelta(days=4)

closest_buoy = Buoy.objects.distance(location).order_by('distance')[0]
data_queryset = buoy.data.filter(date__gte=time_four_days_ago)

# if there are a lot of fields on your BuoyData model,
# and you only need a few, .values will be more performant
data_values = data_queryset.values('date', 'swell_size_ft')
df = read_frame(data_values)
Run Code Online (Sandbox Code Playgroud)

为什么你的方法行不通:

关系数据库(MySQL、Postgresql)通常将数据存储在固定大小的空间中。浮标可能有数百万个时间序列数据点,并且每隔几秒可能会添加新数据。您不知道单个浮标的所有未来数据有多大。

在设置数据库时,需要为特定模型的每个字段的大小设置上限。例如,文本字段具有 max_length 属性。当然,某些类型的字段支持非常大的最大大小,但这会影响数据库的性能。

相反,您需要创建一个单独的表来存储所有数据Buoys。该表中的每一行都是一个单独的时间序列数据。该数据库中的一个字段(列)将是数据所属的id字段。Buoy该字段由 Django 外键自动创建和填充。