2010-11-12 3 views
9

Я новичок в Python и имею, вероятно, очень простой вопрос о «лучшем» способе хранения данных в моем коде. Любые советы очень ценятся!Наиболее подходящая структура данных (Python)

У меня есть длинный файл .csv в следующем формате:

Scenario,Year,Month,Value 
1,1961,1,0.5 
1,1961,2,0.7 
1,1961,3,0.2 
etc. 

Мой сценарий значения серий от 1 до 100, год идет с 1961 по 1990 год и месяц уходит от 1 до 12. Мой файл, следовательно, имеет 100 * 29 * 12 = 34800 строк, каждое со связанным значением.

Я хотел бы прочитать этот файл в какой-то структуре данных Python, чтобы получить доступ к значению «Значение», указав «Сценарий», «Год» и «Месяц». Каков наилучший способ сделать это, пожалуйста (или какие различные варианты)?

В моей голове я рассматриваю эти данные как своего рода «кубический номер» с осями для сценария, года и месяца, так что каждое значение расположено в координатах (сценарий, год, месяц). По этой причине у меня возникает соблазн попытаться прочитать эти значения в трехмерном массиве numpy и использовать индексы Scenario, Year и Month. Это разумная вещь?

Я предполагаю, что я мог бы также сделать словарь, где ключи-то вроде

str(Scenario)+str(Year)+str(Month) 

Будет ли это лучше? Есть ли другие варианты?

(«Лучше», я полагаю, я имею в виду «быстрее получить доступ», хотя, если один из методов намного менее интенсивный в памяти, чем другой, было бы хорошо знать об этом).

Большое спасибо!

+0

Вау - какой фантастический сайт! 5 человек дали мне отличные ответы за меньшее время, чем потребовалось мне, чтобы написать исходный вопрос. СПАСИБО! – JamesS

ответ

8

Я бы воспользовался типом кортежей. Чтобы получить одно значение:

import csv 

reader = csv.reader(open('data.csv', 'rb')) 
header = reader.next() 
data = {} 

for row in reader: 
    key = tuple([int(v) for v in row[:-1]]) 
    val = row[-1] 
    data[key] = float(val) 

# Retrieve a value 
print data[1, 1961, 3] 
+0

Спасибо fmark. Я скопировал и вставил ваш код, и он работал блестяще. Я не ожидал, что кто-нибудь напишет мой код для меня, но вы все равно это сделали :-) – JamesS

+2

Его всегда приятно написать простое решение в python :) – fmark

4

Я бы использовал sqlite3 для хранения данных на диск. Вы сможете прочитать полный набор данных или подмножества через SQL-запросы. Затем вы можете загрузить эти данные в массив numpy или другую структуру данных Python - что наиболее удобно для задачи.

Если вы предпочитаете использовать sqlite, также обратите внимание, что sqlite имеет тип данных TIMESTAMP. Может быть хорошей идеей объединить год и месяц в один TIMESTAMP. Когда вы читаете TIMESTAMPs в Python, sqlite3 может быть предложено автоматически преобразовать TIMESTAMPs в объекты datetime.datetime, что уменьшит часть кода шаблона, который вам пришлось бы написать. Это также упростит формирование SQL-запросов, которые запрашивают все строки между двумя датами.

+0

Cheers unutbu, это звучит неплохо. Я сделаю некоторое чтение и посмотрю, находится ли он в моих нынешних возможностях. Тем временем я буду использовать предложение fmark снизу. – JamesS

+0

@JamesS: Нет проблем. Добро пожаловать в SO! – unutbu

0

Сделайте словарь словарей со словарей, как вы описали. Если вам нужны данные в виде чисел, переведите их в числа один раз, когда вы их прочитаете и сохраните числа в dicts. Это будет быстрее, чем использование строк в качестве ключей. Дайте мне знать, если вам нужна помощь с кодом.

2

sqlite - отличный вариант, если вы каждый раз получаете доступ к своим значениям по разным параметрам.

Если это не так, и вы всегда будете получать доступ к этому триплету (сценарий, год, месяц), вы можете использовать Tuple (неизменный список) в качестве своего ключа и значение в качестве вашего значения.

В коде это будет выглядеть следующим образом:

d = {} 
d[1, 1961, 12] = 0.5 

или более общего кода петли:

d[scenario, year, month] = value 

позже вы можете просто получить к нему доступ с:

print d[scenario, year, month] 

Python будет автоматически создайте Tuple для вас.