python - 如何提高映射函数到熊猫中数据框列的计算速度
问题描述
我正在基于整个数据框中的其他值的数据框中创建一个新列。我已经找到了几种方法(如下所示),但是在处理大型数据集时它们非常慢(运行 500k 行需要 1 小时)。我希望提高这个过程的速度。
我尝试将 .apply 与 lambda 函数一起使用。我还使用 .map 获取要放入新列的列表。这两种方法都有效,但速度太慢。
values = {'ID': ['1','2','3','4','1','2','3'],
'MOD': ['X','Y','Z','X','X','Z','Y'],
'Period': ['Current','Current','Current','Current','Past','Past','Past']
}
df = DataFrame(values,columns= ['ID', 'MOD','Period'])
df['ID_MOD']=df['ID']+df['MOD']
def funct(identifier, indentifier_modification,period):
if period=="Current":
if (df.ID==identifier).sum()==1:
return "New"
elif (df.ID_MOD==indentifier_modification).sum()==1:
return "Unique"
else:
return "Repeat"
else:
return "n/a"
初始df:
ID MOD Period ID_MOD
0 1 X Current 1X
1 2 Y Current 2Y
2 3 Z Current 3Z
3 4 X Current 4X
4 1 X Past 1X
5 2 Z Past 2Z
6 3 Y Past 3Y
以下是两种太慢的方法:1)
df['new_column']=df.apply(lambda x:funct(x['ID'],x['ID_MOD'],x['Period']), axis=1)
2)
df['new_column']=list(map(funct,df['ID'],df['ID_MOD'],df['Period']))
预期的最终df:
ID MOD Period ID_MOD new_column
0 1 X Current 1X Repeat
1 2 Y Current 2Y Unique
2 3 Z Current 3Z Unique
3 4 X Current 4X New
4 1 X Past 1X n/a
5 2 Z Past 2Z n/a
6 3 Y Past 3Y n/a
没有错误信息;使用大型数据集运行代码只需约 1 小时。
解决方案
您当前的代码当前缩放为 O(N**2) 其中 N 是行数。如果你df
真的是 500k 行,这将需要很长时间!你真的想使用计算复杂度低得多的 numpy 和 pandas 的代码。
pandas 中内置的聚合将大大有助于代替您使用. 在你的情况下,我可以很容易地将 500k 行减少到不到一秒钟。sum
merge
首先定义一个虚拟数据集:
import numpy as np
import pandas as pd
N = 500_000
df = pd.DataFrame({
'id': np.random.choice(N//2, N),
'a': np.random.choice(list('XYZ'), N),
'b': np.random.choice(list('CP'), N),
})
接下来,我们可以进行聚合以计算您的各个组:
ids = df.groupby(['id']).size().rename('ids')
idas = df.groupby(['id','a']).size().rename('idas')
接下来我们可以将这些聚合连接回原始数据集
尽可能地减少数据总是一个好主意,在你的情况下,Past
值总是得到一个值,n/a
因为它们占用了一半的数据,所以工作量似乎是一半:
df2 = df.loc[df['b'] == 'C',]
df2 = pd.merge(df2, ids, left_on=['id'], right_index=True)
df2 = pd.merge(df2, idas, left_on=['id','a'], right_index=True)
最后,我们使用where
from numpy 对所有条件进行矢量化,因此工作速度更快,然后使用 pandas 索引将所有内容有效地重新组合在一起,然后修补缺失值
df2['out'] = np.where(
df2['ids'] == 1, 'New',
np.where(df2['idas'] == 1, 'Unique', 'Repeat'))
df['out'] = df2['out']
df['out'].fillna('n/a', inplace=True)
希望其中的一些帮助!作为参考,我的笔记本电脑上 500k 行的上述运行时间约为 320 毫秒
推荐阅读
- webapi - ADO.Net 代码在控制台应用程序中工作。但不适用于 WEB API 项目。数据库位于 AWS
- angular - 没有 zone.js 的角度路由
- azure-devops - 使用脚本创建 Azure Pipeline Build and Release
- java - M3:如何识别 Java 项目中的语法错误
- viewcontroller - 在 iOS 13 和 Xcode 11 中更改根控制器时出现黑屏动画
- python - 如何使用python stackoverflow将值位置更改为每一个
- python - 有没有办法将具有意图和训练短语的 CSV 文件的定义格式转换为 RASA nlu.md 文件?
- node.js - 如何将 Powershell 命令添加到 NPM 脚本?
- c# - 频道主动消息提醒
- javascript - 我怎样才能只留下 bootstrap.bundle.min.js 中需要的部分代码