2010-09-17 9 views
12

In my previous question molti utenti volevano che fornissi altri dati con cui giocare. Quindi ho lavorato sull'esportazione di tutti i miei dati e sull'elaborazione con Python, ma poi ho capito: dove lascio tutti questi dati?Come inserire gli array in un database?

Bene, ho deciso che la cosa migliore sarebbe stata di inserirli in un database, quindi almeno non ho to parse the raw files ogni volta. Ma dal momento che non so nulla dei database questo si sta rivelando piuttosto confuso. Ho provato alcuni tutorial per creare un database SQLite, aggiungere una tabella e un campo e provare ad inserire my numpy.arrays, ma non riesce a farlo funzionare.

In genere i miei risultati per cane simile a questa: alt text

Così ho 35 diversi cani e ogni cane ha 24 di misura. Ogni misura stessa ha una quantità sconosciuta di contatti. Ogni misura è composta da una matrice 3D (248 fotogrammi dell'intera piastra [255x63]) e una matrice 2D (i valori massimi per ciascun sensore della piastra [255x63]). Memorizzare un valore in un database non era un problema, ma il fatto di avere i miei array 2D non sembrava funzionare.

Quindi la mia domanda è come dovrei ordinare questo in un database e inserire i miei array in esso?

+0

Per la divulgazione completa, questo è in discussione in [Chat SuperUser] (http://chat.superuser.com/rooms/11/fake-programmers) adesso :-) – Josh

+0

Il motivo principale è che non sono sarà la persona che lo usa e ho bisogno di una certa garanzia che i miei file siano dove li metto. Inoltre, ovviamente inserirò molti più dati, non solo questi array. Ma gli array mi stanno facendo venire il mal di testa, quindi se riesco a farli entrare, il resto sarà più facile. –

+2

Perché non usare pickle.dump o numpy.dump invece? Quindi puoi semplicemente scaricare i tuoi array multidimensionali nella loro interezza. Non c'è motivo di progettare un database se lo si utilizzerà solo per la persistenza degli oggetti Python. –

risposta

8

Probabilmente si vorrà iniziare con una tabella dogs contenente tutti i dati piane (non array) per ogni cane, cose che ogni cane ha un di, come un nome, un sesso, e un'età:

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

da lì, ogni cane "ha molti" misurazioni, quindi è necessario un tavolo dog_mesaurements per memorizzare i 24 misure:

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

Poi ogni volta che si effettua una misurazione, si INSERT INTO dog_measurements (dog_id,taken_at) VALUES (*?*, NOW()); wher e * ? * è l'ID del cane dalla tabella dogs.

Avrai quindi vuole tabelle per memorizzare i fotogrammi effettivi per ogni misura, qualcosa di simile a:

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

In questo modo, per ciascuno dei 250 telai, si esegue un ciclo attraverso ciascuno dei 63 sensori, e memorizzare il valore di tale sensore con il numero di frame nel database:

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

Ovviamente sostituire measurement_id?, numero frame?, numero_sensore?, valore? con valori reali :-)

Quindi, fondamentalmente, ognuno dog_measurement_data è un valore unico sensore per un determinato lasso. In questo modo, per ottenere tutti i valori del sensore per tutti un determinato lasso, si farebbe:

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` 

E questo vi darà tutte le righe e colonne per quel fotogramma.

+4

Tuttavia, per "zampa" potresti volere qualcosa di più generico dire "appendice". Quindi potresti avere anche un unsigned int per i grandi aracnidi, decapodi, zerg, ecc ... – Tyler

+0

@Tyler: In generale è un ottimo consiglio. In questo caso, Ivo sta lavorando su un software specifico per i cani, ma chi lo sa, il veterinario potrebbe ottenere degli zerg nel prossimo mese! – Josh

+0

Woops @Josh, ho provato la tua istruzione di inserimento e ci sono voluti 6 minuti per inserire una misura :-P Indovinate che dovrei adattarla per usare invece executemany()! E se mai avessi il tempo, [il tuo benvenuto in Drop by Fake Programmers] (http://chat.stackexchange.com/rooms/116/fake-programmers) –

2

Penso che non si sia in grado di capire come inserire i dati 2D nel database.

Se si pensa alla relazione tra 2 colonne, è possibile considerarla come dati 2D con 1a colonna come dati dell'asse X e 2a colonna come dati dell'asse Y. Allo stesso modo per i dati 3D.

Infine vostro db dovrebbe essere simile a questo:

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 

Inoltre si può decidere di memorizzare i dati 3D e dati 2D in un ordine. In tal caso, dovrai aggiungere una colonna per memorizzare quell'ordine nella tabella di dati 3D e dati 2D

2

L'unica cosa che aggiungerei alla risposta di Josh è che se non hai bisogno di interrogare singoli frame o sensori , archivia gli array come BLOB nella tabella dog_measure_data. L'ho già fatto con un grande insieme binario di dati del sensore e ha funzionato bene. Fondamentalmente si interrogano gli array 2d e 3d con ogni misura e li si manipola in codice invece che nel database.

+0

Questo dovrebbe essere stato postato come commento alla mia risposta, ma , Immagino che non puoi ancora postare commenti :-) In risposta, direi che il lato negativo di questo è che hai bisogno di un formato che puoi archiviare/recuperare in modo affidabile da BLOB, come JSON o qualche altro valore python serializzato. Questo potrebbe non essere così facile come sembra! – Josh

7

Django ha una libreria per incapsulare tutto il lavoro del database in classi Python, quindi non è necessario fare confusione con SQL raw finché non si deve fare qualcosa di veramente intelligente. Anche se Django è un framework per applicazioni web, puoi use the database ORM by itself.

modelli di Josh apparirebbe come questo in Python con 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'] 

I id campi vengono creati automaticamente.

Poi si possono fare cose come:

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

per effettuare una misurazione:

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

Infine, per ottenere un frame:

# 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: questo restituirà un lista di tuple (ad es. [(1.5,), (1.8,), ... ]), poiché values_list() può recuperare più campi contemporaneamente. Non ho familiarità con NumPy, ma immagino che abbia una funzione simile alla funzione reshape di Matlab per rimappare i vettori in matrici.

1

Ho tratto molto vantaggio dal sqlalchemy package; è un Object Relational Mapper. Ciò significa che è possibile creare una separazione molto chiara e distinta tra gli oggetti ei suoi dati:

database SQL si comportano meno come oggetto collezioni più dimensioni e inizio prestazioni alla materia; oggetto le raccolte si comportano meno come le tabelle e le righe più l'astrazione inizia per importare. SQLAlchemy mira a soddisfare entrambi questi principi.

È possibile creare oggetti che rappresentano i nomi diversi (cane, misura, piastra, ecc.). Quindi si crea una tabella tramite i costrutti sqlalchemy che conterranno tutti i dati a cui si desidera associare, ad esempio, un oggetto Dog. Infine crei un mapper tra l'oggetto Dog e lo dog_table.

Questo è difficile da comprendere senza un esempio e non ne riprodurrò uno qui. Invece, iniziare leggendo this case study e quindi studiare this tutorial.

Una volta che si può pensare del vostro Dogs e Measurements come si fa nel mondo reale (cioè, gli oggetti stessi) è possibile avviare factoring fuori ai dati che li compone.

Infine, prova a non sposare i tuoi dati con un formato specifico (come fai attualmente usando gli array numpy). Invece, puoi pensare ai numeri semplici e quindi trasformarli su richiesta nel formato specifico richiesto dall'applicazione corrente (sulla falsariga di un paradigma Model-View-Controller).

Buona fortuna!

0

Dalla descrizione, consiglio vivamente di esaminare PyTables. Non è un database relazionale nel senso tradizionale, ha la maggior parte delle funzionalità che probabilmente utilizzerete (ad esempio l'esecuzione di query), consentendo al contempo una facile memorizzazione di set di dati di grandi dimensioni e multidimensionali e dei relativi attributi. Come bonus aggiuntivo, è strettamente integrato con Numpy.

Problemi correlati