2017-05-29 79 views
1

請允許我請求關於Python列表的一些常規建議。我知道我不應該在這裏回答'開放'的問題,但我擔心完全走錯了路。大型嵌套列表與字典

我的問題是,我有.csv文件,每個約600,000行。 .csv的每一行都有6個字段,其中第一個字段是日期時間戳,格式爲DD/MM/YYYY HH:MM:SS。接下來的兩個字段爲空,最後三個字段包含浮點和整數數值,因此,例如:

23/05/2017 16:42:17, , , 1.25545, 1.74733, 12 
23/05/2017 16:42:20, , , 1.93741, 1.52387, 14 
23/05/2017 16:42:23, , , 1.54875, 1.46258, 11 

在第1列(日期時間戳)沒有兩個值將永遠是一樣的。

我需要編寫一個程序,將做一些基本的操作與數據,如:

  1. 讀取所有的數據轉換成字典,列表等設置適當(?)。
  2. 在日期時間戳列中搜索特定值。
  3. 通過列表讀取並對第4列和第5列的花車進行基本計算。
  4. 根據搜索/計算編寫一個新列表。

我的問題是 - 我該如何「處理」數據,並且由於數據集的長度,我可能會遇到問題?

例如,我應該將所有數據導入到列表中,並且列表中的每個元素都是每行數據的子列表?例如:

[[23/05/2017 16:42:17,'','', 1.25545, 1.74733, 12],[23/05/2017 16:42:20,'','', 1.93741, 1.52387, 14], ...]

或者它會更好地使每個日期時間戳在字典中的「鑰匙」,使詞典「價值」與其他所有值的列表,如:

{'23/05/2017 16:42:17': [ , , 1.25545, 1.74733, 12], ...}

如果我使用列表的方式,有沒有辦法讓Python僅在第一欄「搜索」特定的時間印記,而不是使之通過60萬行次搜索6列,當我們知道只有第一列包含時間戳?

我很抱歉如果我的查詢有點含糊,但會很感激任何人都可以提供的指導。

+0

對於搜索,字典縮放O(log(n)),列出O(n)(除了當entrys被排序時,也可以使其成爲O(log(n)))。這是你的一個論點嗎?如果按比例放大,您可以使用擱架來儘量減少所需的內存。 – hajef

+0

當你說「根據搜索/計算寫一個新列表」。你的意思是把它寫入文件?基本上,你是否試圖編輯文件中的一行? – EyuelDK

+0

這聽起來像你一定要去字典選項。你可能想看看'csv' python模塊,它可以幫助你輕鬆地將數據讀到字典中。 –

回答

2

600000行不是那麼多,你的腳本應該運行良好的列表或字典。

作爲一個測試,我們使用:

data = [["2017-05-02 17:28:24", 0.85260, 1.16218, 7], 
["2017-05-04 05:40:07", 0.72118, 0.47710, 15], 
["2017-05-07 19:27:53", 1.79476, 0.47496, 14], 
["2017-05-09 01:57:10", 0.44123, 0.13711, 16], 
["2017-05-11 07:22:57", 0.17481, 0.69468, 0], 
["2017-05-12 10:11:01", 0.27553, 0.47834, 4], 
["2017-05-15 05:20:36", 0.01719, 0.51249, 7], 
["2017-05-17 14:01:13", 0.35977, 0.50052, 7], 
["2017-05-17 22:05:33", 1.68628, 1.90881, 13], 
["2017-05-18 14:44:14", 0.32217, 0.96715, 14], 
["2017-05-18 20:24:23", 0.90819, 0.36773, 5], 
["2017-05-21 12:15:20", 0.49456, 1.12508, 5], 
["2017-05-22 07:46:18", 0.59015, 1.04352, 6], 
["2017-05-26 01:49:38", 0.44455, 0.26669, 13], 
["2017-05-26 18:55:24", 1.33678, 1.24181, 7]] 

字典

如果你正在尋找確切的時間戳,查找會快很多了字典比列表。但是,您必須確切知道您在尋找什麼:"23/05/2017 16:42:17""23/05/2017 16:42:18"有完全不同的散列。

data_as_dict = {l[0]: l[1:] for l in data} 
print(data_as_dict) 
# {'2017-05-21 12:15:20': [0.49456, 1.12508, 5], '2017-05-18 14:44:14': [0.32217, 0.96715, 14], '2017-05-04 05:40:07': [0.72118, 0.4771, 15], '2017-05-26 01:49:38': [0.44455, 0.26669, 13], '2017-05-17 14:01:13': [0.35977, 0.50052, 7], '2017-05-15 05:20:36': [0.01719, 0.51249, 7], '2017-05-26 18:55:24': [1.33678, 1.24181, 7], '2017-05-07 19:27:53': [1.79476, 0.47496, 14], '2017-05-17 22:05:33': [1.68628, 1.90881, 13], '2017-05-02 17:28:24': [0.8526, 1.16218, 7], '2017-05-22 07:46:18': [0.59015, 1.04352, 6], '2017-05-11 07:22:57': [0.17481, 0.69468, 0], '2017-05-18 20:24:23': [0.90819, 0.36773, 5], '2017-05-12 10:11:01': [0.27553, 0.47834, 4], '2017-05-09 01:57:10': [0.44123, 0.13711, 16]} 

print(data_as_dict.get('2017-05-17 14:01:13')) 
# [0.35977, 0.50052, 7] 

print(data_as_dict.get('2017-05-17 14:01:10')) 
# None 

請注意,您DD/MM/YYYY HH:MM:SS格式是不是很方便:分選細胞字典順序不會被日期時間對它們進行排序。你需要使用datetime.strptime()第一:

from datetime import datetime 
data_as_dict = {datetime.strptime(l[0], '%Y-%m-%d %H:%M:%S'): l[1:] for l in data}  
print(data_as_dict.get(datetime(2017,5,17,14,1,13))) 
# [0.35977, 0.50052, 7] 

print(data_as_dict.get(datetime(2017,5,17,14,1,10))) 
# None 

列表與二進制搜索

如果您正在尋找時間戳範圍,一個字典不會幫助你多少。在時間戳列表上進行二分搜索(例如使用​​)應該非常快。

import bisect 
timestamps = [datetime.strptime(l[0], '%Y-%m-%d %H:%M:%S') for l in data] 
i = bisect.bisect(timestamps, datetime(2017,5,17,14,1,10)) 
print(data[i-1]) 
# ['2017-05-15 05:20:36', 0.01719, 0.51249, 7] 
print(data[i]) 
# ['2017-05-17 14:01:13', 0.35977, 0.50052, 7] 

數據庫

重新發明輪子之前,您可能希望將所有的CSV轉儲到一個小型的數據庫(SQLite的和PostgreSQL,...),並使用相應的查詢。

熊貓

如果你不想數據庫增加了複雜性,但準備投資一些時間學習一種新的語法,你應該使用pandas.DataFrame。它確實是你想要的,然後是一些。

+0

謝謝@Eric Duminil提供瞭如此全面而有益的回覆 - 這絕對給了我一些開始。根據我上面的評論,'csv數據'始終按時間順序排列,通常每3秒鐘有一個數據點,但並非總是如此。我將尋找一個特定的時間(精確到秒),但是由於datastamps是每個〜3秒只有它有可能是特別郵票進出口尋找沒有原始數據存在,在這種情況下,我會解決的找到一個「附近」的數據點。非常感謝您花時間幫助我! – Paul