Python 如何有效地将数据框中的条目映射到字典
很长一段时间以来,我一直是stackoverflow的粉丝,我发现它非常有用。然而,这次我觉得有必要问一个关于我所写代码的性能相关问题,我希望我能从社区得到一些有价值的帮助 我的问题涉及在“用户”数据框(见下文)中向给定用户推荐广告的问题,其中“adids”数据框中的每个广告必须满足某些标准才能推荐给用户。数据在以下表格中:Python 如何有效地将数据框中的条目映射到字典,python,python-3.x,dictionary,optimization,pandas,Python,Python 3.x,Dictionary,Optimization,Pandas,很长一段时间以来,我一直是stackoverflow的粉丝,我发现它非常有用。然而,这次我觉得有必要问一个关于我所写代码的性能相关问题,我希望我能从社区得到一些有价值的帮助 我的问题涉及在“用户”数据框(见下文)中向给定用户推荐广告的问题,其中“adids”数据框中的每个广告必须满足某些标准才能推荐给用户。数据在以下表格中: users = pd.DataFrame({"loginid" : [0, 0, 0, 1, 1, 0], "min_price" :
users = pd.DataFrame({"loginid" : [0, 0, 0, 1, 1, 0],
"min_price" : [10, 10, 10, 20, 20, 10],
"max_price" : [30, 30, 30, 40, 40, 30],
"municipal" : ["a", "b", "c", "d", "e", "e"] })
ads数据框如下所示:
adids = pd.DataFrame({"adid" : [100, 101, 102, 103, 104, 105],
"totalprice" : [11., 15, 15, 25, 35, 25],
"municipal" : ["a", "a", "d", "d", "e", "d"]})
我想要(有效地)实现的是对给定用户(即给定loginid)的相关广告进行过滤。目前,我正在填充一个名为“adsdict”的字典,其中键是用户的loginid,值都是推荐的adid。如果“totalprice”介于用户的最大和最小价格范围(由“min_price”和“max_price”给出)之间,并且用户在市政方面也有匹配项,则建议使用广告。下面的代码实现了这一点,但是,我不确定我这样做的效率有多高。在我的完整数据集上,这是一个非常大的数据集(10^6++行的顺序),当涉及到时间消耗时,这部分绝对是我的瓶颈
adsdict = {}
unique_logins = np.unique(users.loginid)
for logid in unique_logins:
row_indexer = (users.loginid == logid)
user = users[row_indexer]
max_price = user.ix[row_indexer, "max_price"].max()
min_price = user.ix[row_indexer, "min_price"].min()
row_indexer_2 = (adids.totalprice >= min_price) \
& (adids.totalprice <= max_price)
ads = adids.loc[row_indexer_2, ["adid", "municipal"]]
adsdict[logid] = list( pd.merge(user, ads, on="municipal").adid.values )
这是理想的结果。然而,正如前面所指定的,我担心我的编码方式是低效的,因为我必须为每个loginid执行连接操作
如果更有经验的python用户(我正在使用Python3.4和pandas 0.16.2)能够就如何优化这一点提供建议,我将不胜感激。我对各种(快速!)解决方案都持开放态度,但内存也是一个因素(尽管我可以访问内存丰富的服务器,所以这不是目前最关键的问题。)因此,解决方案甚至不需要使用字典,我唯一的标准是能够看到向给定用户推荐了哪些广告(loginid)
提前谢谢
问候,
马格纳斯
另外,当我在这里发布queston时,我已经尝试过遵守最佳实践。如果我忽略了提供必要的信息,我提前表示歉意。因此,首先您需要从
广告中找到匹配市政的用户,您可以通过合并两个帧来实现这一点,这就是您满足第一个条件的方式
In [15]:
match_minicipal_df = pd.merge(users , adids , on = 'municipal')
match_minicipal_df
Out[15]:
loginid max_price min_price municipal adid totalprice
0 30 10 a 100 11
0 30 10 a 101 15
1 40 20 d 102 15
1 40 20 d 103 25
1 40 20 d 105 25
1 40 20 e 104 35
0 30 10 e 104 35
然后,为了满足第二个条件,即总计
应介于最小值
和最大值
之间,您可以通过
In [32]:
match = np.logical_and(match_minicipal_df.totalprice > match_minicipal_df.min_price , match_minicipal_df.totalprice < match_minicipal_df.max_price)
match
Out[32]:
0 True
1 True
2 False
3 True
4 True
5 True
6 False
dtype: bool
正如你在这里看到的
In [53]:
match_minicipal_df.ix[match ,['loginid' , 'adid'] ]
Out[53]:
loginid adid
0 100
0 101
1 103
1 105
1 104
非常感谢良信电器,非常感谢。答案也很快。
In [33]:
match_minicipal_df[match]
Out[33]:
loginid max_price min_price municipal adid totalprice
0 30 10 a 100 11
0 30 10 a 101 15
1 40 20 d 103 25
1 40 20 d 105 25
1 40 20 e 104 35
In [53]:
match_minicipal_df.ix[match ,['loginid' , 'adid'] ]
Out[53]:
loginid adid
0 100
0 101
1 103
1 105
1 104