How to insert arrays into a database?
在我之前的问题中,很多用户希望我提供更多的数据来玩。所以我开始导出我的所有数据并用python处理它,但后来我意识到:我应该把这些数据放在哪里?
好吧,我决定最好的办法是将它们保存在数据库中,这样至少我不必每次都分析原始文件。但由于我对数据库一无所知,这就变得非常混乱。我尝试了一些教程来创建一个sqlite数据库,添加一个表和字段,并尝试插入我的numpy.array,但是它不能使它工作。
通常我每只狗的结果如下:
所以我有35只不同的狗,每只狗有24个尺寸。每个测量本身都有一个未知数量的触点。每个测量由一个三维阵列(248帧整板[255x63])和一个二维阵列(每个板传感器的最大值[255x63])组成。在数据库中存储一个值并不是问题,但在其中获取二维数组似乎不起作用。
所以我的问题是如何在数据库中排序并将数组插入其中?
您可能希望从包含每只狗的所有平面(非数组)数据的
1 2 3 4 5 6 | CREATE TABLE `dogs` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, `name` VARCHAR(64), `age` INT UNSIGNED, `sex` ENUM('Male','Female') ); |
从那里开始,每只狗"有许多"测量值,因此您需要一个
1 2 3 4 5 6 | 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 ); |
那么,无论何时进行测量,你都要在哪里*?*是
然后,您将希望表格存储每个度量的实际帧,例如:
1 2 3 4 5 6 7 8 | 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个传感器中的每一个,并将带有帧号的传感器值存储到数据库中:
1 2 | INSERT INTO `dog_measurement_data` (`dog_measurement_id`,`frame`,`sensor_row`,`sensor_col`,`value`) VALUES (*measurement_id?*, *frame_number?*, *sensor_row?*, *sensor_col?*, *value?*) |
显然要替换测量值?框架数?,传感器编号?价值?带实值:—)
因此,基本上,每个
1 2 3 | 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` |
这会给你这个框架的所有行和列。
Django有一个库,可以将所有数据库工作封装到Python类中,所以在必须做一些真正聪明的事情之前,您不必处理原始SQL。尽管Django是一个Web应用程序的框架,但您可以单独使用数据库ORM。
乔希的模型在使用django的python中应该是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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'] |
自动创建
然后你可以做如下的事情:
1 2 3 4 5 6 7 8 9 | 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') |
要进行测量:
1 2 3 4 5 6 | 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]) |
最后,要得到一个帧:
1 2 3 4 5 6 7 | # 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') |
注意:这将返回一个元组列表(例如
我要补充到乔希的答案中的唯一一件事就是,如果你不需要查询单独的帧或传感器,只需将数组存储为dog_measurement_数据表中的blobs。我以前用大量的二进制传感器数据做过这个,结果很好。基本上,您可以查询每个测量的二维和三维数组,并在代码中而不是数据库中操作它们。
我想你不知道如何把二维数据放到数据库中。
如果考虑两列之间的关系,可以将其视为二维数据,第一列为X轴数据,第二列为Y轴数据。同样适用于3D数据。
最后,您的数据库应该如下所示:
1 2 3 4 5 6 7 8 9 10 11 | 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 |
另外,您可能希望按顺序存储三维数据和二维数据。在这种情况下,您必须添加一列,以将该顺序存储在三维数据和二维数据表中。
我从
SQL databases behave less like object
collections the more size and
performance start to matter; object
collections behave less like tables
and rows the more abstraction starts
to matter. SQLAlchemy aims to
accommodate both of these principles.
您可以创建一个表示不同名词(dog、measurement、plate等)的对象。然后,通过
如果没有一个例子,这是很难理解的,我不会在这里复制一个。相反,请先阅读本案例研究,然后学习本教程。
一旦你能想象你的
最后,不要将您的数据与特定的格式结合起来(就像您目前使用
祝你好运!
根据您的描述,我强烈建议您查看Pytables。它不是传统意义上的关系数据库,它具有您可能使用的大多数功能(例如查询),同时允许轻松存储大型多维数据集及其属性。作为额外的奖励,它与numpy紧密结合。