如何将数组插入数据库?

19 投票
6 回答
11898 浏览
提问于 2025-04-16 04:17

在我之前的问题中,很多用户希望我提供更多的数据来玩玩。所以我开始导出我的所有数据,并用Python处理它,但我突然意识到:我该把这些数据放在哪里呢?

我决定最好的办法是把它们放进一个数据库,这样我就不需要每次都去解析那些原始文件了。但是因为我对数据库一无所知,这让我感到相当困惑。我尝试了一些教程,想创建一个sqlite数据库,添加一个表和字段,然后试着把我的numpy数组插进去,但就是搞不定。

通常我每只狗的结果看起来是这样的: alt text

我有35只不同的狗,每只狗有24个测量值。每个测量值本身有不确定数量的接触点。每个测量由一个3D数组(整个板的248帧 [255x63])和一个2D数组(每个传感器的最大值 [255x63])组成。把一个值存进数据库不是问题,但把我的2D数组放进去似乎就不行。

所以我想知道,我应该如何在数据库中组织这些数据,并把我的数组插进去呢?

6 个回答

2

我觉得你可能还不太明白怎么把二维数据放进数据库里。

如果你想象一下两列之间的关系,可以把它看作是二维数据,第一列就像是X轴的数据,第二列就是Y轴的数据。三维数据也是这样理解。

最后,你的数据库应该是这个样子的:

Table: Dogs
    Columns: DogId, DogName -- contains data for each dog

Table: Measurements
    Columns: DogId, MeasurementId, 3D_DataId, 2D_DataId -- contains measurements of each dog

Table: 3D_data
    Columns: 3D_DataId, 3D_X, 3D_Y, 3D_Z -- contains all 3D data of a measurement

Table: 2D_data
    Columns: 2D_DataId, 2D_X, 2D_Y -- contains all 2D data of a measurement

另外,如果你想把三维数据和二维数据按顺序存储,那你需要在三维数据和二维数据的表里加一列,用来记录这个顺序。

7

Django 有一个库,可以把所有数据库的操作封装成 Python 类,这样你就不用直接写复杂的 SQL 语句,直到你需要做一些特别复杂的事情。虽然 Django 是一个用于网页应用的框架,但你也可以单独使用它的数据库 ORM

Josh 的模型在 Python 中使用 Django 看起来是这样的:

from django.db import models

class Dog(models.Model):
    # Might want to look at storing birthday instead of age.
    # If you track age, you probably need another field telling
    # you when in the year age goes up by 1... and at that point,
    # you're really storing a birthday.
    name = models.CharField(max_length=64)
    age = models.IntegerField()
    genders = [
        ('M', 'Male'),
        ('F', 'Female'),
    ]
    gender = models.CharField(max_length=1, choices=genders)

class Measurement(models.Model):
    dog = models.ForeignKey(Dog, related_name="measurements")
    paws = [
        ('FL', 'Front Left'),
        ('FR', 'Front Right'),
        ('RL', 'Rear Left'),
        ('RR', 'Rear Right'),
    ]
    paw = models.CharField(max_length=2, choices=paws)
    taken_at = models.DateTimeField(default=date, auto_now_add=True)

class Measurement_Point(models.Model):
    measurement = models.ForeignKey(Measurement, related_name="data_points")
    frame = models.IntegerField()
    sensor_row = models.PositiveIntegerField()
    sensor_col = models.PositiveIntegerField()
    value = models.FloatField()

    class Meta:
        ordering = ['frame', 'sensor_row', 'sensor_col']

这里的 id 字段是自动生成的。

然后你可以做一些事情,比如:

dog = Dog()
dog.name = "Pochi"
dog.age = 3
dog.gender = 'M'
# dog.gender will return 'M', and dog.get_gender_display() will return 'Male'
dog.save()

# Or, written another way:
dog = Dog.objects.create(name="Fido", age=3, sex='M')

进行测量:

measurement = dog.measurements.create(paw='FL')
for frame in range(248):
    for row in range(255):
        for col in range(63):
            measurement.data_points.create(frame=frame, sensor_row=row, 
                sensor_col=col, value=myData[frame][row][col])

最后,获取一个数据框:

# For the sake of argument, assuming the dogs have unique names.
# If not, you'll need some more fields in the Dog model to disambiguate.
dog = Dog.objects.get(name="Pochi", sex='M')
# For example, grab the latest measurement...
measurement = dog.measurements.all().order_by('-taken_at')[0]
# `theFrameNumber` has to be set somewhere...
theFrame = measurement.filter(frame=theFrameNumber).values_list('value')

注意:这会返回一个元组的列表(例如 [(1.5,), (1.8,), ... ]),因为 values_list() 可以一次获取多个字段。我对 NumPy 不太熟悉,但我想它应该有一个类似于 Matlab 中 reshape 函数的功能,用于将向量重新映射为矩阵。

9

你可能想先建立一个 dogs 表,这个表里包含每只狗的基本信息,比如名字、性别和年龄,这些信息每只狗只有一个:

CREATE TABLE `dogs` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(64),
  `age` INT UNSIGNED,
  `sex` ENUM('Male','Female')
);

接下来,每只狗都有很多测量数据,所以你需要一个 dog_measurements 表来存储24个测量值:

CREATE TABLE `dog_measurements` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `dog_id` INT UNSIGNED NOT NULL,
  `paw` ENUM ('Front Left','Front Right','Rear Left','Rear Right'),
  `taken_at` DATETIME NOT NULL
);

每当你进行一次测量时,你可以用这个命令 INSERT INTO dog_measurements (dog_id,taken_at) VALUES (*?*, NOW());,其中 * ? * 是从 dogs 表中获取的狗的ID。

然后你还需要一些表来存储每次测量的具体数据,比如:

CREATE TABLE `dog_measurement_data` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `dog_measurement_id` INT UNSIGNED NOT NULL,
  `frame` INT UNSIGNED,
  `sensor_row` INT UNSIGNED,
  `sensor_col` INT UNSIGNED,
  `value` NUMBER
);

这样,对于每250个数据帧,你就可以遍历63个传感器,把每个传感器在该帧的值存入数据库:

INSERT INTO `dog_measurement_data` (`dog_measurement_id`,`frame`,`sensor_row`,`sensor_col`,`value`) VALUES
(*measurement_id?*, *frame_number?*, *sensor_row?*, *sensor_col?*, *value?*)

当然,要把 measurement_id?frame_number?sensor_number?value? 替换成真实的值 :-)

所以基本上,每个 dog_measurement_data 就是某个帧的 单个传感器的值。这样,如果你想获取某个帧的所有传感器值,你可以:

SELECT `sensor_row`,sensor_col`,`value` FROM `dog_measurement_data`
WHERE `dog_measurement_id`=*some measurement id* AND `frame`=*some frame number*
ORDER BY `sensor_row`,`sensor_col`

这样就能得到该帧的所有行和列数据。

撰写回答