2017-05-29 77 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