【发布时间】:2023-01-10 08:34:49
【问题描述】:
我编写了两个嵌套的函数,它们通过过滤另一个数据帧 (df2) 并将其转换为具有某种逻辑的列表来扩展一个数据帧 (df1)。这个例子当然只是一个很小的例子。 df1 和 df2 实际上要大得多。由于这个过程需要很多行的大量时间,我想在性能方面优化脚本。这样功能本身就可以尽可能快地工作,然后可以并行化。我已经使用 Swifter 运行了并行化。但是,这不再以某种方式起作用。我想 Swifter 不是这个的最佳模块?
这是数据框:
df1 = pd.DataFrame({'name':['10004', '20005', '10003', 'X2'],
'group':['1', '2', '3', 'X2'],
'code':['H', 'H', 'H', 'R'],
'start':[2, 3, 5, 2],
'end':[5, 8, 8, 5] })
df2 = pd.DataFrame({'name': 5*['10004'] + 10*['20005'] + 8*['10003'] + 6*['X2'],
'group':5*['1'] + 10*['2'] + 8*['3'] + 6*['X2'],
'code': 5*['H'] + 10*['H'] + 8*['H'] + 6*['R'],
'ID':list(range(1,6)) +
list(range(1,11)) +
list(range(1,9)) +
list(range(1,7)),
'ConcFZ':['1', '1,2' , '', '3', '4',
'3,4', '3', '3', '2', '', '2', '', '2,1', '1', '1',
'8', '5','6', '', '6', '', '2', '2',
'3', '3', '3,2,1', '2', '2', '1'],
'NumFZ':[1, 2 , 0, 1, 1,
2, 1, 1, 1, 0, 1, 0, 2, 1, 1,
1, 1,1, 0, 1, 0, 1, 1,
1, 1, 3, 1, 1, 1]})
和功能:
def Filter_df(row, counter=0):
df_filtered = df2[df2['name'].isin([row['name']])&
df2['group'].isin([row['group']])&
df2['code'].isin([row['code']])&
~df2['NumFZ'].isin([0])]\
.set_index('ID')\
.loc[row['start']:row['end']]\
.drop_duplicates(subset='ConcFZ', keep='last')[['ConcFZ', 'NumFZ']]
if df_filtered.size == 0:
print('No Data at Index:', row.name)
return []
else:
return TzToList(df_filtered)
def TzToList(df_filtered):
TWTZ = df_filtered[df_filtered['NumFZ'] == 1]['ConcFZ'].astype(int).tolist()
if df_filtered.shape[0] == 1 and df_filtered.iat[0,1] > 1:
tz=[]
tz=[
int(df_filtered['ConcFZ'].str.split(',').iat[0][f])
for f in range(0, len(df_filtered['ConcFZ'].str.split(',').iat[0][:]))
]
tz.sort
TWTZ.append(tz[0])
elif df_filtered.shape[0] == 1 and df_filtered.iat[0,1] == 1:
pass
elif df_filtered.iat[0,1] == 0:
print('LRILred.iat[0,1] == 0?: ', df_filtered.iat[0,1])
else:
df_filtered_g1 = df_filtered[df_filtered['NumFZ'] >1]
for i in range(0, df_filtered_g1.shape[0]):
tz=[]
tz=[
int(df_filtered_g1['ConcFZ'].str.split(',').iat[i][f])
for f in range(0, len(df_filtered_g1['ConcFZ'].str.split(',').iat[i][:]))
]
tz.sort
if len(list(set(tz).intersection(TWTZ))) == 0:
TWTZ.append(tz[0])
else:
continue
return TWTZ
如您所见,函数“Filter_df”使用 df1 中的一些行值来过滤 df2 并返回函数 TzToList 的输出。 TzToList 采用过滤后的 df,进一步简化此数据,并将结果转换为列表。此列表将作为列表列添加到 df1。
我这样做是这样的:
df1['Filtered'] = df1.apply(Filter_df, axis=1)
我的python版本是:3.9.13 我的熊猫版本是:1.5.2 我在带有 jupyter-lab 的 jupyter notebook 中使用这个脚本
这是 Filtered_df 函数的第一个版本,它比上面那个慢:
def Filter_df_1(row, counter=0):
df_filtered = df2[(df2['name']==row['name'])&
(df2['group']==row['group'])&
(df2['code']==row['code'])&
(df2['NumFZ']!=0)]\
.set_index('ID')\
.loc[row['start']:row['end']]\
.drop_duplicates(subset='ConcFZ', keep='last')[['ConcFZ', 'NumFZ']]
if df_filtered.size==0:
print('No Data at Index:', row.name)
return []
else:
return TzToList(df_filtered)
并行化在 win10 上与 Filter_df_1 和 swifter 以及在我的 Linux 系统上使用 pandarallel 一起工作。不知何故,它不再与 swifter 一起工作。
import swifter
df1['Filtered'] = df1.swifter.apply(Filter_df, axis=1)
无论如何,我需要在具有 32 核 CPU 和 64 线程的 Win10 上运行该程序。 最好使用的模块是什么?达斯克?以及如何使用它?
【问题讨论】:
标签: python pandas optimization parallel-processing