我正在基于整个数据框中的其他值在数据框中创建一个新列。我发现了几种方法(如下所示),但是在处理大型数据集时(运行50万行需要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个小时即可运行大型数据集。
答案 0 :(得分:0)
您当前的代码当前缩放为O(N ** 2),其中N是行数。如果您的df
确实有50万行,这将需要很长时间!您真的想使用numpy和pandas的代码,它们的计算复杂度要低得多。
内置到大熊猫中的aggregations会大大代替您使用sum
,就像了解熊猫如何建立索引和merge
一样。在您的情况下,我可以很容易地将50万行减少到不到一秒。
首先定义一个虚拟数据集:
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)
最后,我们使用numpy中的where
对您的所有条件进行矢量化处理,从而更快地进行工作,然后使用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)
希望其中一些帮助!供参考,上面的代码在我的笔记本电脑上以50万行在320ms内运行