2010-09-17 165 views
12

In my previous question很多用户希望我给玩具提供更多的数据。所以我开始着手导出所有数据并使用Python进行处理,但后来我意识到:我在哪里可以保留所有这些数据?如何将数组插入数据库?

好吧,我决定最好的事情是将它们粘贴在数据库中,所以至少我没有每次都有to parse the raw files。但由于我对数据库一无所知,这变得相当混乱。我尝试了一些教程来创建一个sqlite数据库,添加一个表和字段,并尝试插入我的numpy.arrays,但它不能让它工作。

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

所以,我有35种不同的狗,每只狗都有24测量。每个测量本身具有未知数量的接触。每个测量由一个3D阵列(整个平板的248个框架[255x63])和一个2D阵列(平板每个传感器的最大值[255x63])组成。在数据库中存储一个值不是问题,但是在那里获取我的二维数组似乎不起作用。

所以我的问题是我应该如何命令这在数据库中,并插入我的数组?

+0

为了充分披露,现在正在[SuperUser Chat](http://chat.superuser.com/rooms/11/fake-programmers)中讨论这个问题:-) – Josh 2010-09-17 19:35:16

+0

主要原因是我没有将成为使用它的人,我需要一些保证,我的文件是我把它们放在哪里。另外显然我会插入更多的数据,而不仅仅是这些数组。但是阵列给我头痛,所以如果我能把它们弄进去,其余的会更容易 – 2010-09-17 19:46:29

+2

为什么不使用pickle.dump或numpy.dump呢?然后,您可以完全转储您的多维数组。没有理由设计一个数据库,如果你只是想用它来保存python对象。 – 2010-09-17 19:59:54

回答

8

你可能会想从一个包含每只狗的所有扁平(非数组)数据的dogs表开始,每只狗都有一个一个,如名字,性别和年龄:

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

从那里,每个狗“有很多个”测量,所以你需要一个dog_mesaurements表来存储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()); wher e * *是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?值?与:-)

实数值因此,基本上,每个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` 

这将为您提供该帧的所有行和列。

+4

虽然,'爪子'你可能想要更通用的东西说,“附件”。那么你可以让它成为大蜘蛛,decapods,虫族等等的无符号int ... – Tyler 2010-11-27 22:54:42

+0

@Tyler:总的来说,这是很好的建议。在这种情况下,Ivo正在开发专门针对狗的软件,但是谁知道,兽医可能会在下个月得到一些Zergs! – Josh 2010-11-28 15:08:59

+0

Woops @Josh,我尝试了你的插入语句,并花了6分钟插入一个测量:-P猜猜我应该适应它使用executemany()来代替!如果你有时间,[你的欢迎由虚拟程序员放弃](http://chat.stackexchange.com/rooms/116/fake-programmers) – 2011-03-27 13:38:42

2

我认为你无法弄清楚如何将二维数据放入数据库。

如果你认为2列之间的关系,你可以把它看作与第一列作为X轴数据和第二栏为Y轴数据的二维数据。对于3D数据也是如此。

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

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 

你也可能要你的3D数据和2D数据存储在一个数量级。在这种情况下,你将不得不增加一列,以顺序存储在3D数据和2D数据的表格

2

我会增加约什的答案的唯一的事情是,如果你不需要查询单个帧或传感器,只需将数组作为BLOB存储在dog_measurement_data表中即可。我之前用大量的二进制传感器数据完成了这一工作,并且工作得很好。基本上查询每个测量的2d和3d阵列,并在代码而不是数据库中操纵它们。

+0

这应该已发布为我的答案的评论,但,我猜你现在还不能发表评论:-)作为回应,我想说这样做的缺点是,你需要一种可以可靠地从BLOB存储/检索的格式,例如JSON或其他一些序列化的python值。这可能不像听起来那么容易! – Josh 2010-09-17 19:52:12

7

Django具有用于封装所有的数据库工作纳入Python类图书馆,这样你就不必使用原始SQL烂摊子,直到你有做一些真正聪明。尽管Django是一个Web应用程序框架,但您可以使用use the database ORM by itself

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函数的函数,用于将向量重新映射为矩阵。

1

我受益匪浅的sqlalchemy package;它是一个对象关系映射器。这意味着,你可以创建你的对象和你的数据之间有非常明确和独特的分离:

SQL数据库的行为不像对象 集合了较具规模和 性能开始关系;反对 集合类的表现不怎么样表 和行更抽象开始 无关紧要。 SQLAlchemy旨在 适应这两个原则。

您可以创建一个代表您的不同名词(狗,测量,板等)的对象。然后你通过sqlalchemy建立一个表格,它将包含你想要关联的所有数据,比如说一个Dog对象。最后,在Dog对象和dog_table之间创建一个mapper

这是很难理解的,没有一个例子,我不会在这里重现一个。相反,请先阅读this case study,然后研究this tutorial

一旦你可以认为你Dogs,当你在现实世界中做Measurements的(即对象本身),你就可以开始分解出,使他们的数据。

最后,尽量不要用特定的格式来结婚(如你目前使用numpy阵列)。相反,您可以考虑简单的数字,然后根据需要将它们转换为您当前应用程序所需的特定格式(沿着模型 - 视图 - 控制器范例的方向)。

祝你好运!

0

从您的描述,我强烈建议调查PyTables。它不是传统意义上的关系数据库,它具有您可能使用的大多数功能(例如查询),同时允许轻松存储大型多维数据集及其属性。作为额外的好处,它与numpy紧密结合。