Python 大型嵌套列表与字典
请允许我征求一些关于Python列表的一般建议。我知道我不应该在这里回答“开放性”问题,但我担心会走上完全错误的道路 我的问题是,我有一个.csv文件,每个文件大约有600000行长。.csv的每一行有6个字段,其中第一个字段是格式为DD/MM/YYYY HH:MM:SS的日期时间戳。接下来的两个字段为空,最后三个字段包含浮点值和整数值,例如:Python 大型嵌套列表与字典,python,dictionary,nested-lists,Python,Dictionary,Nested Lists,请允许我征求一些关于Python列表的一般建议。我知道我不应该在这里回答“开放性”问题,但我担心会走上完全错误的道路 我的问题是,我有一个.csv文件,每个文件大约有600000行长。.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,
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列(日期时间戳)中的任何两个值都不会相同
我需要编写一个程序,对数据进行一些基本操作,例如:
[[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只在第一列中“搜索”特定的时间戳,而不是在我们知道只有第一列包含时间戳时,让它搜索600000行乘以6列
如果我的问题有点模糊,我深表歉意,但希望任何人都能提供指导。600000行没有那么多,您的脚本应该可以使用列表或dict运行良好 作为测试,让我们使用:
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]]
字典
如果您要查找准确的时间戳,那么使用dict进行查找要比使用列表快得多。不过,您必须确切地知道自己在寻找什么:“23/05/2017 16:42:17”
的哈希值与“23/05/2017 16:42:18”
的哈希值完全不同
请注意,您的DD/MM/YYYY HH:MM:SS
格式不太方便:按字典顺序排序单元格不会按日期时间排序。您首先需要使用:
二进制搜索列表
如果你在寻找时间戳范围,dict对你没有多大帮助。对时间戳列表进行二进制搜索(例如,使用)应该非常快
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等)中,并使用相应的查询
熊猫
如果您不想增加数据库的复杂性,但准备投入一些时间学习新语法,那么应该使用。它完全按照您的要求执行,然后执行一些。对于搜索,dicts scale O(log(n)),list O(n)(除非入口已排序,否则您也可以将其设置为O(log(n))。这是你的论点吗?如果你扩大规模,你也许可以使用一个架子来最小化所需的内存。当你说“根据搜索/计算写一个新的列表”时,你的意思是把它写到文件中吗?基本上,您是在试图编辑文件中的一行吗?听起来您肯定应该使用dictionary选项。您可能想看看
csv
python模块,它可以帮助您轻松地将数据读入dict。您的时间戳是精确的还是正在搜索“最近的”时间戳?您的CSV文件是否按时间戳排序?如果要查找精确的时间戳,那么在字典中查找密钥需要恒定的时间(O(1)),不需要扫描。如果您不是在寻找精确匹配,但您的数据是有序的,请使用列表并使用二分法(请参阅二分法
模块)。我认为熊猫库值得在这里尝试一下。感谢@Eric Duminil提供如此全面和有帮助的回答-这无疑给了我一些入门的机会。根据我上面的评论,“csv数据”总是按时间顺序排列,通常每3秒有一个数据点,但并不总是如此。我将搜索一个特定的时间(精确到秒),但由于数据戳仅为每3秒一次,因此我查找的特定戳可能不存在于原始数据中,在这种情况下,我将满足于查找“附近”的数据点。再次感谢你抽出时间来帮助我!
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]