在Python中使用大型临时数据库清洗数据
我有一大堆数据要从一个xml文件中提取,这些数据需要相互验证(超过50万条记录)。这些数据是位置信息,包括县、街道前缀、街道后缀、街道名称、起始门牌号和结束门牌号等。里面有重复的记录、门牌号重叠等等,我需要对这些数据进行报告(比如指出哪些地方有问题)。而且,xml文件中的数据没有顺序,所以每条记录都需要和其他所有记录进行匹配。
现在我正在根据街道名称信息创建一个字典,然后存储一个包含起始和结束门牌号位置的列表。在这一切完成后,我会遍历这个庞大的数据结构,找出每个列表中的重复和重叠记录。但我在处理这个数据结构的大小和出现的错误数量时遇到了问题。
有人建议我创建一个临时的SQLite数据库,把所有从文件中读取的数据存进去,然后在数据库中查找所有数据问题,报告出来后再删除这个数据库。有没有更好或者更有效的方法来解决这个问题?有什么建议可以更好地处理这个问题吗?
顺便提一下,我读取的xml文件超过500MB(里面存储的不仅仅是街道信息,虽然这部分占了大头),但处理文件本身并不是我遇到的问题,问题出现在处理从文件中获得的数据时。
编辑:我可以说得更详细一点,但提到内存空间充足的那位朋友其实是对的,虽然在某个情况下我确实需要处理350万条记录,那时候我确实需要创建一个临时数据库。
2 个回答
除非这些数据已经经过处理,符合PAF(英国邮政地址文件 - 基本上包含了英国的每一个地址),否则你可能会发现有些地址是同一个房子,但拼写不同、邮政编码错误、邮政编码放错地方等等。这会完全改变你的处理方式。
在开始之前,先确认一下这些数据是否已经处理过。给你数据的人要么会说“当然处理过了,我做的”,要么就会一脸茫然——如果是后者,那肯定没处理过。
如果已经处理过,那就太好了,可能是外部机构在提供你的数据,他们也许能帮你处理这些问题,但我想你之所以被问到这个,可能是因为这样更便宜。继续吧。
如果没有处理过,那你就会面临一系列问题,需要和你的老板讨论他们想要什么,以及他们对匹配结果的信心程度等等。
一般来说,想法是为每个字段设计几个匹配算法,输出一个信心值,用来判断两个地址是否相同。然后,这些信心值会被加权,最后得出一个总的信心值,只有当这个值达到一定标准时,才会认为这两个地址是匹配的。
不过我不太确定这是否是你的问题,但我建议你先确认一下老板到底想要什么——在市场部门和技术部门之间,这个领域并不是特别明确。
50万这个数字其实并不算大,为什么你不能把所有记录都遍历一遍,创建一个字典,把相关的条目放进去,然后检查你需要检查的内容呢?比如:
import random
import time
class Data(object):
ID = 0
def __init__(self, data):
Data.ID+=1
self.id =Data.ID
self.data = data
self.duplicates = None
def fill_data(N):
data_list = []
# create alist of random data
sample = list("anuraguniyal")
for i in range(N):
random.shuffle(sample)
data_list.append(Data("".join(sample)))
return data_list
def find_duplicate(data_list):
data_map = {}
for data in data_list:
if data.data in data_map:
data_map[data.data].append(data)
else:
data_map[data.data] = [data]
data.duplicates = data_map[data.data]
st = time.time()
data_list = fill_data(500000)
print "fill_data time:", time.time()-st
st = time.time()
find_duplicate(data_list)
print "find_duplicate time:", time.time()-st
total_duplicates = 0
max_duplicates = 0
for data in data_list:
total_duplicates += (len(data.duplicates) - 1)
max_duplicates = max(len(data.duplicates),max_duplicates)
print "total_duplicates count:",total_duplicates
print "max_duplicates count:",max_duplicates
输出:
fill_data time: 7.83853507042
find_duplicate time: 2.55058097839
total_duplicates count: 12348
max_duplicates count: 3
那么你的情况和这个例子有什么不同呢?能不能用类似的方法来处理?