Pandas 在多处理中使用多个参数 apply()



我有一个由一百万条记录组成的大数据集(在下面的代码片段中表示为只有 5 行的big_df(,我想在调用调用classify function的 apply 函数时使用多处理。

问题陈述 数据集由 1M 组成,每行包括列idname,最新的列name包括标点符号和停用词,这些标点符号和停用词使用 regex 删除。然后,我们可以假设数据帧中显示的名称已被清理。

对于每条记录,都需要逐字逐句地确定该词是在开头还是/和结尾使用,它可以是两者兼而有之。例如,如果我们有单词ABC SECONDARY SCHOOL BOARDING

  • ABC只是在同名ABC SCHOOL BOARDING的开头, 它没有classification end.然后,它在classification start处计为 1 .

  • SECONDARY是第二个词,它不是 在开头和结尾都没有找到。然后,它被分类 作为none.

  • SCHOOL是第三个词,它出现在MARIE INSTITUTE SCHOOLRALPH ELEMENTARY SCHOOLBOARDING SCHOOL的末尾。 然后,它在classification end处算作 3 .
  • BOARDING是第四个单词,在ABC SCHOOL BOARDING的末尾找到,在classification end处算作 1。另外,BOARDING在开头找到BOARDING SCHOOL,则计为: 1 在classification start
  • .

此过程一直持续到到达所有行。然后,执行聚合以获取单词在开头和/或结尾的次数,如果没有,则该单词被归类为none

以下是使用apply调用函数classify的工作版本:

import pandas as pd
Data=[[0,'ABC SECONDARY SCHOOL BOARDING',['ABC','SECONDARY','SCHOOL','BOARDING']],
[1,'UNIVERSITY BOARDING INSTITUTE',['UNIVERSITY','BOARDING','INSTITUTE']],
[2,'MARIE INSTITUTE SCHOOL',['MARIE', 'INSTITUTE','SCHOOL']],
[3,'RALPH ELEMENTARY SCHOOL',['RALPH','ELEMENTARY','SCHOOL']],
[4,'BOARDING SCHOOL',['BOARDING','SCHOOL']]]
df_big=pd.DataFrame(Data, columns=['id','name', 'name_list'])
df_class = pd.DataFrame(columns=['word','classification'])
df_class2 = pd.DataFrame(columns=['word','classification'])
def classify(row,start,end):
d=[]
for word in row.name_list:
flag=False
if word in start.values:
d.append([word,'start'])
flag=True
if word in end.values:
d.append([word,'end'])
flag=True
if (not flag):
d.append([word,'none'])
return d  
df_start=pd.DataFrame(columns=['name'])
df_end=pd.DataFrame(columns=['name'])
df_start= df_big.name.str.split().str.get(0).drop_duplicates(keep="last")
df_end= df_big.name.str.split().str.get(-1).drop_duplicates(keep="last")
lst=[]
lst = df.apply(classify, args=[df_start, df_end],axis=1)
flat_list = [item for sublist in lst for item in sublist]
lst=[]
for e in flat_list:
lst.append(e)
print("--------")
print("Dataframe classified:")
df2=pd.DataFrame(lst, columns=['word', 'classification'])
print(df2)
print("Summary")
df2.index.names = ['id']
df2.reset_index(inplace=True, drop=True)
count_series=df2.groupby(['word','classification']).size()
df_count = count_series.to_frame(name = 'counter').reset_index()
print(df_count)

这将提供如下结果:

Dataframe classified:
word classification
0          ABC          start
1    SECONDARY           none <------SPECIAL CASE, NOT CLASSIFIED
2       SCHOOL            end
3     BOARDING          start
4     BOARDING            end
5   UNIVERSITY          start
6     BOARDING          start
7     BOARDING            end
8    INSTITUTE            end
9        MARIE          start
10   INSTITUTE            end
11      SCHOOL            end
12       RALPH          start
13  ELEMENTARY           none <------SPECIAL CASE, NOT CLASSIFIED
14      SCHOOL            end
15    BOARDING          start
16    BOARDING            end
17      SCHOOL            end
Summary
word classification  counter
0         ABC          start        1
1    BOARDING            end        3
2    BOARDING          start        3
3  ELEMENTARY           none        1  <---NONE
4   INSTITUTE            end        2
5       MARIE          start        1
6       RALPH          start        1
7      SCHOOL            end        4
8   SECONDARY           none        1  <---NONE
9  UNIVERSITY          start        1

基本上,每个单词都分为startendnone

上述版本正在工作并产生显示的结果。但是,对于由百万条记录组成的数据集,这会延迟大约 10 个小时。我需要以更快的方式做同样的事情。在我的搜索中,我想出了multiprocessing,通过根据内核数量拆分大数据集并并行运行数据集的每个部分来帮助加快该过程。

然后,我添加了以下修改:

def process(df,df_start,df_end):
return df.apply(classify, args=[df_start, df_end],axis=1)   
p = mp.Pool(processes=8)
split_dfs = np.array_split(big_df,8)
pool_results = p.map(process, split_dfs)
p.close()
p.join()
# merging parts processed by different processes
parts = pd.concat(pool_results, axis=0)
# merging newly calculated parts to big_df
big_df = pd.concat([big_df, parts], axis=1)
# checking if the dfs were merged correctly
pdt.assert_series_equal(parts['id'], big_df['id'])

但是,此修改仍在运行,没有结果。我想知道如何以更快的方式使用多个参数使用 apply((。

感谢您的帮助:)

Python(以及固有的 Pandas(经常难以处理更大的数据集(特别是如果函数没有矢量化 - 请参阅有关如何改进它的体面文章此处(没有一些特殊的设置。

将其放在次要位置并尝试解决手头的问题(在值列表中查找匹配的单词(:

您可以为end单词创建一个数据框,为start单词创建一个数据框(假设单词既可以是start又可以是end(。

然后,您需要进行两次左合并。这些应该很快。

out_start=pd_big.merge(pd_start,left_on='word',right_on='word',how='left')
out_both=out_start.merge(pd_end,left_on='word',right_on='word',how='left')

您可能需要进行一些重新命名,但这应该要快得多。

你可以在这里找到更多关于熊猫合并的信息:(https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.merge.html(

相关内容

  • 没有找到相关文章

最新更新