2010-09-17 20 views
12

In my previous question muchos usuarios querían que le diera más datos para jugar. Así que trabajé exportando todos mis datos y procesándolos con Python, pero luego me di cuenta: ¿dónde dejo todos estos datos?¿Cómo insertar matrices en una base de datos?

Bueno, decidí que lo mejor sería pegarlos en una base de datos, por lo que al menos no tengo to parse the raw files cada vez. Pero como no sé nada de las bases de datos, esto resulta bastante confuso. Intenté algunos tutoriales para crear una base de datos sqlite, agregar una tabla y un campo y tratar de insertar mis numpy.arrays, pero no puede hacer que funcione.

Normalmente mis resultados por perro tener este aspecto: alt text

Así que tengo 35 perros diferentes y cada perro tiene 24 medición. Cada medida en sí tiene una cantidad desconocida de contactos. Cada medición consta de una matriz 3D (248 fotogramas de la placa completa [255x63]) y una matriz 2D (los valores máximos para cada sensor de la placa [255x63]). Almacenar un valor en una base de datos no era un problema, pero no parecía que funcionaran mis arrays 2D.

Así que mi pregunta es ¿cómo debo ordenar esto en una base de datos e insertar mis matrices en él?

+0

Para una divulgación completa, esto se está discutiendo en [SuperUser Chat] (http://chat.superuser.com/rooms/11/fake-programmers) en este momento :-) – Josh

+0

La razón principal es que no estoy va a ser la persona que lo usa y necesito cierta garantía de que mis archivos están donde los coloqué. Además, obviamente voy a insertar mucha más información, no solo estas matrices. Pero las matrices me están dando dolor de cabeza, así que si puedo obtenerlas, el resto será más fácil –

+2

¿Por qué no utilizar pickle.dump o numpy.dump en su lugar? Entonces puedes simplemente volcar tus matrices multidimensionales en su totalidad. No hay motivo para diseñar una base de datos si solo vas a usarla para la persistencia de los objetos de Python. –

Respuesta

8

Usted probablemente querrá comenzar con una mesa dogs que contiene todos los datos planas (no de la matriz) para cada perro, lo que cada perro tiene una de, como un nombre, un sexo y edad:

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

a partir de ahí, cada perro "tiene muchas" medidas, por lo que necesita una mesa dog_mesaurements para almacenar las 24 mediciones:

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 
); 

Entonces cada vez que tome una medición, INSERT INTO dog_measurements (dog_id,taken_at) VALUES (*?*, NOW()); RCEst e * ? * es la identificación del perro de la tabla dogs.

A continuación, desea tablas para almacenar los marcos reales para cada medición, algo así como:

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 
); 

De esta manera, para cada uno de los 250 marcos, se recorre cada uno de los sensores 63, y almacenar el valor de ese sensor con el número de cuadro en la base de datos:

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

reemplazar Obviamente measurement_id?, frame_number?, sensor_number?, valor? con los valores reales :-)

Así que, básicamente, cada dog_measurement_data es un valor único sensor para una trama dada. De esta manera, para obtener todos los valores de los sensores para todos una trama dada, lo haría:

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` 

Y esto le dará todas las filas y columnas para esa trama.

+4

Sin embargo, para 'pata' es posible que desee algo más genérico decir, "apéndice". Entonces podrías tener también un int sin firmar para los grandes arácnidos, decápodos, zerg, etc ... – Tyler

+0

@Tyler: En general, ese es un gran consejo. En este caso, Ivo está trabajando en un software específico para perros, pero quién sabe si el veterinario puede obtener algunos Zergs el próximo mes. – Josh

+0

Woops @Josh, probé tu declaración de inserción y me llevó 6 minutos insertar una medida :-P Supongo que debería adaptarla para usar executemany(). Y si alguna vez tiene el tiempo, [su bienvenida a caer por los programadores falsos] (http://chat.stackexchange.com/rooms/116/fake-programmers) –

2

Creo que no es posible averiguar cómo poner datos 2D en la base de datos.

Si considera la relación entre 2 columnas, puede considerarla como datos 2D con la 1ra columna como datos del eje X y la 2da columna como datos del eje Y. Del mismo modo para datos 3D.

Finalmente su base de datos debe tener este aspecto:

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 

También es posible que desee almacenar sus datos en 3D y 2D de datos en un orden. En ese caso, tendrá que agregar una columna para almacenar ese orden en la tabla de datos 3D y datos 2D

2

Lo único que agregaría a la respuesta de Josh es que, si no necesita consultar cuadros o sensores individuales , simplemente almacene las matrices como BLOB en la tabla dog_measurement_data. He hecho esto antes con un gran conjunto binario de datos de sensores y funcionó bien. Básicamente consultas las matrices 2D y 3D con cada medida y las manipulas en código en lugar de en la base de datos.

+0

Esto debería haber sido publicado como un comentario a mi respuesta, pero , Supongo que no puedes publicar comentarios todavía :-) En respuesta, diría que la desventaja de esto es que necesitas un formato que puedas almacenar/recuperar confiablemente de BLOB, como JSON o algún otro valor de python serializado. ¡Esto podría no ser tan fácil como parece! – Josh

7

Django tiene una biblioteca para encapsular todo el trabajo de la base de datos en clases de Python, por lo que no tiene que meterse con SQL sin procesar hasta que tenga que hacer algo realmente inteligente. Aunque Django es un marco para aplicaciones web, puede use the database ORM by itself.

modelos de Josh se vería así en Python usando 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'] 

Los campos id se crean automáticamente.

A continuación, puede hacer cosas como:

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') 

Para realizar una medición:

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]) 

Por último, para obtener un marco:

# 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') 

Nota: Esto devolverá una lista de tuplas (por ejemplo, [(1.5,), (1.8,), ... ]), ya que values_list() puede recuperar múltiples campos a la vez. No estoy familiarizado con NumPy, pero me imagino que tiene una función similar a la función reshape de Matlab para reasignar vectores a matrices.

1

Me he beneficiado mucho del sqlalchemy package; es un asignador relacional de objetos. Lo que esto significa es que se puede crear una separación muy clara y distinta entre sus objetos y sus datos:

bases de datos SQL se comportan menos como objeto colecciones más tamaño y rendimiento inicio a la materia; objeto colecciones se comportan menos como las tablas y filas más abstracción comienza a la materia. SQLAlchemy tiene como objetivo acomodar estos dos principios.

Puede crear objetos que representen sus diferentes nombres (perro, medida, placa, etc.). A continuación, crea una tabla a través de constructos sqlalchemy que contendrán todos los datos que desea asociar con, por ejemplo, un objeto Dog. Finalmente crea un mapper entre el objeto Dog y el dog_table.

Esto es difícil de entender sin un ejemplo, y no voy a reproducir uno aquí. En su lugar, comience por leer this case study y luego estudie this tutorial.

Una vez que pueda pensar en su Dogs y Measurements como lo hace en el mundo real (es decir, los objetos en sí) puede comenzar a factorizar los datos que los componen.

Por último, intente no casar sus datos con un formato específico (como lo hace actualmente usando las matrices numpy). En su lugar, puede pensar en los números simples y luego transformarlos según demanda al formato específico que su aplicación actual demanda (siguiendo el modelo de un paradigma Modelo-Vista-Controlador).

¡Buena suerte!

0

De su descripción, recomendaría encarecidamente buscar en PyTables. No es una base de datos relacional en el sentido tradicional, tiene la mayoría de las características que probablemente utilizará (por ejemplo, consultas) al mismo tiempo que permite un fácil almacenamiento de grandes conjuntos de datos multidimensionales y sus atributos. Como una ventaja adicional, está estrechamente integrado con numpy.

Cuestiones relacionadas