给出购买事件列表(客户编号,商品)
1-hammer
1-screwdriver
1-nails
2-hammer
2-nails
3-screws
3-screwdriver
4-nails
4-screws
我试图构建一个数据结构,它告诉你一件商品和另一件商品一起购买了多少次。不是同时买的,而是我开始保存数据后买的。结果看起来像
^{pr2}$表示锤子用钉子买了两次(人1、3),螺丝刀买了一次(人1),螺丝刀买了一次(人3),以此类推。。。在
我目前的做法是
users=dict,其中userid是键,购买的项目列表是值
usersfritem=dict,其中itemid是键,购买item的用户列表是值
userlist=对当前项目进行评级的用户的临时列表
pseudo:
for each event(customer,item)(sorted by item):
add user to users dict if not exists, and add the items
add item to items dict if not exists, and add the user
----------
for item,user in rows:
# add the user to the users dict if they don't already exist.
users[user]=users.get(user,[])
# append the current item_id to the list of items rated by the current user
users[user].append(item)
if item != last_item:
# we just started a new item which means we just finished processing an item
# write the userlist for the last item to the usersForItem dictionary.
if last_item != None:
usersForItem[last_item]=userlist
userlist=[user]
last_item = item
items.append(item)
else:
userlist.append(user)
usersForItem[last_item]=userlist
所以,在这一点上,我有两个结论-谁买了什么,什么是谁买的。这就是问题的症结所在。现在usersWrite已经填充完毕,我将遍历它,遍历每个购买该项的用户,并查看用户的其他购买行为。我承认这并不是最具Python式的做事方式——我在尝试在使用Python之前确保得到正确的结果(我就是这样)。在
relatedItems = {}
for key,listOfUsers in usersForItem.iteritems():
relatedItems[key]={}
related=[]
for ux in listOfReaders:
for itemRead in users[ux]:
if itemRead != key:
if itemRead not in related:
related.append(itemRead)
relatedItems[key][itemRead]= relatedItems[key].get(itemRead,0) + 1
calc jaccard/tanimoto similarity between relatedItems[key] and its values
有没有更有效的方法可以让我这样做?另外,如果这种手术有合适的学术名称,我很乐意听到。在
编辑:澄清包括我没有限制购买同时购买的物品。物品可以随时购买。在
你真的需要预先计算所有可能的对吗?如果你懒洋洋地做,也就是按需办事呢?在
可以用二维矩阵表示。行对应于客户,列对应于产品。在
每个条目都是0或1,表示与列对应的产品是否由行对应的客户购买。在
如果你把每一列看作(大约5000)0和1的向量,那么两个乘积一起购买的次数就是相应向量的点乘!在
因此,你可以先计算这些向量,然后根据需要懒洋洋地计算点积。在
要计算点积:
现在,只有0和1的向量的一个好的表示是一个整数数组,它基本上是一个位图。在
对于5000个条目,需要79个64位整数的数组。在
因此,给定两个这样的数组,您需要计算常见的1的数量。在
要计算两个整数共有的位数,首先可以按位计算,然后再计算结果数中设置的1的数量。在
为此,您可以使用查找表或一些位计数方法(不确定python是否支持它们),例如:http://graphics.stanford.edu/~seander/bithacks.html
所以你的算法是这样的:
为每个产品初始化79个64位整数的数组。
对于每个客户,查看购买的产品并在相应的产品中为该客户设置适当的位。
现在给出两个产品的查询,你需要知道一起购买它们的客户数量,只需按照上面描述的dot产品。
这应该相当快。在
作为进一步的优化,您可以考虑将客户分组。在
保罗的答案也许是最好的,但以下是我在午休时想到的(诚然,这还没有经过测试,但仍然是一个有趣的思考练习)。不确定我的算法是否快速/优化。我个人建议看看类似MongoDB的NoSQL数据库,因为它似乎可以很好地解决此类问题(map/reduce等等)
给出:
^{pr2}$(这将按购买事件处理您的初始请求分组项目。要按用户分组,只需将事件列表的第一个键从event number更改为user id。)
相关问题 更多 >
编程相关推荐