我一直在试验一个应用程序,我遇到了这个问题。我有一个规则列表,如下面给出的规则。这是实验数据,实际数据有更多的字段(30+)。每条记录都可以包含一些值和一些空值。这是一个列表列表,但我也可以在defaultdict中保存它(如果它有帮助)。大约100万条记录。
Age Gender City Religion Propensity
23 * Delhi * 0.33
* M Mumbai * 0.78
* * * Hindu 0.23
34 F Chennai * 0.33
...
...
...
现在我有一个数据集 - (23,M,德里,印度教),其中包含所有值。
我需要选择上表中与该记录匹配的所有记录,即使是一维以最快的速度按维度的降序排列。因此,在这种情况下,第3行和第1行匹配。因此,具有最少空值的记录将位于底部。
我需要一种复杂的方法来实现这一点,它在python中进行扩展。不能使用任何其他软件。
答案 0 :(得分:0)
您可以将数据存储在一组词典中:
dict1:age->list<entry>
dict2:gender->list<entry>
...
现在,当您收到查询时 - 您所要做的就是创建一个histogram(map:entry-&gt;整数),根据值对其进行排序,然后按降序打印。
运行时间为O(d*m + mlogm)
(平均),其中d
是列表数(维度),m
是输出条目的数量。
<强>伪码:强>
assume list of dictionaries, let it be L:
printRelevants(entry):
histogram <- new dictionary
for each dimension d:
l <- L[d].get(entry[d])
for each element e in l: #remember to check for null l first
val <- histogram.get(e)
if val is null:
histogram.put(e,1)
else:
histogram.put(e,val+1) #assuming overriding old entry with the same key
#done creating the histogram!
sort histogram according to value
print keys of histogram in descending order
答案 1 :(得分:0)
假设您的“搜索条件”始终相同,即“数据集”(年龄,性别,城市,宗教信仰)
将其移至由“数据集”
索引的列表(或集合)字典result_dict = {}
for record in record_list:
# you have to know the indexes
# I'm assuming 0=Age, 1=Gender, 2=City, 3=Hindu
key_data = []
for index in [0, 1, 2, 3]:
key_data.append(str(record[index]))
key = ','.join(key_data)
try:
result_dict[key].append(record)
except KeyError:
result_dict[key] = []
result_dict[key].append(record)
# Find all records that match '23,M,Delhi,Hindu'
print result_dict['23,M,Delhi,Hindu']
但实际上,我可能已将其存储在数据库中,只是在其上运行SQL查询。
答案 2 :(得分:0)
假设您使用了注释中提到的SQL数据库(sqlite3),SQL将如下所示:
-- gives you the set of complete records
SELECT
v0.*
FROM values v0
WHERE -- only full records
v0.Age IS NOT NULL
AND v0.Gender IS NOT NULL
AND v0.City IS NOT NULL
AND v0.Religion IS NOT NULL
AND v0.Propensity IS NOT NULL
SELECT v1.*,
CASE v1.Age WHEN IS NULL THEN 0 ELSE 1 END +
CASE v1.Gender WHEN IS NULL THEN 0 ELSE 1 END +
CASE v1.City WHEN IS NULL THEN 0 ELSE 1 END +
CASE v1.Religion WHEN IS NULL THEN 0 ELSE 1 END +
CASE v1.Propensity WHEN IS NULL THEN 0 ELSE 1 END as dimensions
FROM values v1
WHERE v1.Age = 23
OR v1.Gender = 'M'
OR v1.City = 'Delhi'
OR v1.Religion = 'Hindu'
ORDER BY dimensions desc
答案 3 :(得分:0)
这里有几个好的答案。我已经编写并测试了一些代码。
首先,这是一个天真的要求实施:
import pprint
t = [
[ 23, None, 'Delhi', None, 0.33 ],
[ None, 'M', 'Mumbai', None, 0.78 ],
[ None, None, None, 'Hindu', 0.23 ],
[ 34, 'F', 'Chennai', None, 0.33 ],
]
rlen = len(t[0])
# None may require special handling
m = [23, 'M', 'Delhi', 'Hindu', None]
a = [[] for i in range(rlen+1)]
for r in t:
s = sum([1 for i in range(rlen) if r[i] == m[i]])
if 0 < s:
a[s].append(r)
# Print rows from least matching to most matching (easy to reverse)
rtable = [row for n in a for row in n]
pprint.pprint(rtable)
问题是我们扫描每一行并检查每个元素值。为了避免在最后排序,我们为每个可能的匹配计数保留单独的列表,然后我们将最终结果的列表列表展平。我希望这相对于表的大小执行大约O(n),如果我们有大量匹配则更糟糕(构建一个大的结果列表将比O(n)慢,接近O(n ^ 2)作为一个最坏的情况)。
我们可以加快速度如果我们索引表格。我们可以使用每列一个dict并使用集合组合列。
from collections import defaultdict
import pprint
# data table
TABLE = [
[ 23, None, 'Delhi', None, 0.33 ],
[ None, 'M', 'Mumbai', None, 0.78 ],
[ None, None, None, 'Hindu', 0.23 ],
[ 34, 'F', 'Chennai', None, 0.33 ],
]
# The index is a list of dicts, cdictlist.
# cdictlist is indexed by column number to get the column dict.
# The column dict's key is the data value of the column
def BuildIndex(table):
rlen = len(table[0])
rrange = range(rlen)
cdictlist = [defaultdict(set) for i in range(rlen+1)]
for ir in range(len(table)):
r = table[ir]
for ic in rrange:
f = r[ic]
cdictlist[ic][f].add(ir)
return cdictlist
def multisearch(table, match, cdictlist):
# rcounts is row counts, number of times columns have matched for a row
rccounts = defaultdict(int)
#rset is the result set, set of row indexes returned for this search
rset = set()
for ic in range(len(table[0])):
cset = cdictlist[ic].get(match[ic], set())
rset = rset.union(cset)
for i in cset:
rccounts[i] += 1
# sort the list by column match count, original row index
l = sorted((v,k) for (k,v) in rccounts.iteritems())
# return list of rows, for each row we return (count, index, raw data)
lr = [ [l[i][0], l[i][1]] + table[l[i][1]] for i in range(len(l)) ]
return lr
def main():
cdictlist = BuildIndex(TABLE)
# None may require special handling
match = [23, 'M', 'Delhi', 'Hindu', None]
lr = multisearch(TABLE, match, cdictlist)
pprint.pprint(lr)
if __name__ == '__main__':
main()
性能取决于返回的记录数而不是表的大小。对于大量匹配,set union操作很快就会成为问题。如果任何字段匹配并且其中一个示例字段是Gender,则记录匹配,因此我们应该期望至少返回一半的行。
如果必须匹配所有列,这种方法可以更好地工作 。我们可以通过构建记录集 NOT (使用set intersection),然后过滤掉这些记录来改进这一点。