Как вставить массивы в базу данных?

В моем предыдущем вопросе многие пользователи хотели, чтобы я дал дополнительные данные для игры. Поэтому я работал над экспортом всех моих данных и обработкой его с помощью Python, но потом понял: где я могу оставить все эти данные?

Ну, я решил, что лучше всего будет вставлять их в базу данных, поэтому, по крайней мере, мне не нужно каждый раз анализировать необработанные файлы . Но так как я ничего не знаю о базах данных, это выглядит довольно запутанным. Я пробовал некоторые учебные пособия для создания базы данных sqlite, добавления таблицы и поля и попытки вставить мой numpy.arrays, но он не может заставить его работать.

Обычно мои результаты для каждой собаки выглядят так: alt text

Таким образом, у меня есть 35 разных собак, и у каждой собаки есть 24 измерения. Каждое измерение имеет неизвестное количество контактов. Каждое измерение состоит из трехмерного массива (248 кадров всей пластины [255×63]) и 2D-матрицы (максимальные значения для каждого датчика пластины [255×63]). Хранение одного значения в базе данных не было проблемой, но получение 2D-массивов там не работало.

Поэтому мой вопрос заключается в том, как я должен делать это в базе данных и вставлять в нее свои массивы?

Вы, вероятно, захотите начать с таблицы с 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()); где * ? * ID dogs стола для dogs .

Затем вам понадобятся таблицы для хранения фактических кадров для каждого измерения, например:

 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?*) 

Очевидно, заменить measure_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` 

И это даст вам все строки и столбцы для этого фрейма.

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, но я бы предположил, что у него есть функция, аналогичная функции reshape Matlab для переназначения векторов на матрицы.

Я думаю, вы не можете понять, как разместить 2D-данные в базе данных.

Если вы думаете о соотношении между двумя столбцами, вы можете рассматривать его как 2D-данные с 1-м столбцом как данные оси X и 2-й столбец как данные оси Y. Аналогично для 3D-данных.

Наконец, ваш db должен выглядеть так:

 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 в заказе. В этом случае вам нужно будет добавить столбец для хранения этого порядка в таблице трехмерных данных и 2D-данных

Единственное, что я хотел бы добавить к ответу Джоша, это то, что если вам не нужно запрашивать отдельные кадры или датчики, просто храните массивы в виде BLOB в таблице dog_measurement_data. Я сделал это раньше с большим двоичным набором данных датчика, и это получилось хорошо. Вы в основном запрашиваете 2d и 3d массивы с каждым измерением и манипулируете ими в коде вместо базы данных.

Я много выиграл от пакета sqlalchemy ; это объектный реляционный сопоставитель. Это означает, что вы можете создать очень четкое и четкое разделение между вашими объектами и вашими данными:

Базы данных SQL ведут себя не так, как коллекции объектов, тем больше размер и производительность начинают иметь значение; коллекции объектов ведут себя не так, как таблицы и строки, тем больше абстракция начинает иметь значение. SQLAlchemy стремится учесть оба этих принципа.

Вы можете создавать объекты, представляющие ваши разные существительные (Dog, Measurement, Plate и т. Д.). Затем вы создаете таблицу через конструкции sqlalchemy которая будет содержать все данные, которые вы хотите связать, скажем, с объектом Dog . Наконец, вы создаете mapper между объектом Dog и dog_table .

Это трудно понять без примера, и я не буду воспроизводить его здесь. Вместо этого, пожалуйста, начните с чтения этого примера, а затем изучите этот учебник .

Как только вы сможете думать о своих Dogs и Measurements как вы это делаете в реальном мире (то есть сами объекты), вы можете начать факторинг данных, которые их создают.

Наконец, постарайтесь не вступать в брак с вашими данными в определенном формате (как в настоящее время с помощью массивов numpy ). Вместо этого вы можете думать о простых числах, а затем преобразовывать их по требованию в конкретный формат, который требует ваше текущее приложение (в соответствии с парадигмой Model-View-Controller).

Удачи!

Из вашего описания я настоятельно рекомендую посмотреть на PyTables . Это не реляционная база данных в традиционном смысле, она имеет большинство функций, которые вы, вероятно, будете использовать (например, запрос), позволяя легко хранить большие, многомерные наборы данных и их атрибуты. В качестве дополнительного бонуса он тесно интегрирован с numpy.