使用来自另一个DataFrame的值将列有效地添加到Pandas DataFrame

时间:2018-10-05 11:17:23

标签: python pandas performance dataframe series

我有一个简单的数据库,其中包含2个表(例如,项目和用户),其中用户的一列是他们的 User_ID ,项目的一列是他们的 Item_ID ,而“商品”的另一列是 User_ID的外键,例如:

Items                                       Users
Item_ID  Value_A  Its_User_ID ...           User_ID  Name  ...
1        35       1                         1        Alice
2        991      1                         2        John
3        20       2  

想象一下我想denormalize这个数据库,即出于查询数据的性能原因,我将表Users中的Name列的值添加到表Items中。我当前的解决方案如下:

items['User_Name'] = pd.Series([users.loc[users['User_ID']==x, 'Name'].iloc[0] 
                     for x in items['Its_User_ID']])

也就是说,我将该列添加为根据理解列表构建的Pandas系列,该列表使用 .loc [] 来检索具有特定ID的用户名,并使用 .iloc [0] 以获取选择的第一个元素(由于用户ID是唯一的,因此这是唯一的元素)。

但是,这种解决方案对于大型商品而言确实很慢。我做了以下测试:

  • 对于1000个项目和约200K用户:20秒。
  • 对于〜400K项和〜200K用户:2.5小时。 (这是实际数据大小)。

因为这种方法是按列的,所以它的执行时间乘以我正在执行此过程的列数成倍增加,并且变得太费时间。虽然我没有尝试使用 for 循环逐行填充新的Series,但我希望它的成本更高。还有其他我忽略的方法吗?是否有可能需要几分钟而不是几个小时的解决方案?

2 个答案:

答案 0 :(得分:1)

我认为,如果您使用表merges,会更简单。

items.merge(users[['User_ID', 'Name']], left_on='Its_User_ID', right_on='User_ID', how='left')

这会将“名称”列添加到新数据集中,您当然可以稍后对其进行重命名。这将比通过for循环逐列进行操作更为有效。

答案 1 :(得分:1)

使用Panda提供的高性能数据库操作,请参见here

例如:

pd.merge(items, users, left_on='Its_User_ID', right_on='User_ID')