【发布时间】:2020-12-26 19:24:33
【问题描述】:
我正在处理一个包含日期和文本数据的大型数据框(约 10M 行),并且我有一个值列表,我需要针对该列表中的每个值进行一些计算。
对于每个值,我需要根据 4 个条件过滤/子集我的数据框,然后进行计算并继续下一个值。 目前,大约 80% 的时间花在过滤器块上,使得处理时间非常长(几个小时)
我目前拥有的是这样的:
for val in unique_list: # iterate on values in a list
if val is not None or val != kip: # as long as its an acceptable value
for year_num in range(1, 6): # split by years
# filter and make intermediate df based on per value & per year calculation
cond_1 = df[f'{kip}'].str.contains(re.escape(str(val)), na=False)
cond_2 = df[f'{kip}'].notna()
cond_3 = df['Date'].dt.year < 2015 + year_num
cond_4 = df['Date'].dt.year >= 2015 + year_num -1
temp_df = df[cond_1 & cond_2 & cond_3 & cond_4].copy()
条件 1 大约需要 45% 的时间,而条件 3 和 4 分别需要 22%
有没有更好的方法来实现这一点?有没有办法删除.dt 和.str 并使用更快的东西?
3 个值的时间(以千计)
总时间:16.338 秒
Line # Hits Time Per Hit % Time Line Contents
==============================================================
1 def get_word_counts(df, kip, unique_list):
2 # to hold predictors
3 1 1929.0 1929.0 0.0 predictors_df = pd.DataFrame(index=[f'{kip}'])
4 1 2.0 2.0 0.0 n = 0
5
6 3 7.0 2.3 0.0 for val in unique_list: # iterate on values in a list
7 3 3.0 1.0 0.0 if val is not None or val != kip: # as long as its an acceptable value
8 18 39.0 2.2 0.0 for year_num in range(1, 6): # split by years
9
10 # filter and make intermediate df based on per value & per year calculation
11 15 7358029.0 490535.3 45.0 cond_1 = df[f'{kip}'].str.contains(re.escape(str(val)), na=False)
12 15 992250.0 66150.0 6.1 cond_2 = df[f'{kip}'].notna()
13 15 3723789.0 248252.6 22.8 cond_3 = df['Date'].dt.year < 2015 + year_num
14 15 3733879.0 248925.3 22.9 cond_4 = df['Date'].dt.year >= 2015 + year_num -1
数据主要是这样的(我在计算时只使用相关的列):
Date Ingredient
20 2016-07-20 Magnesium
21 2020-02-18 <NA>
22 2016-01-28 Apple;Cherry;Lemon;Olives General;Peanut Butter
23 2015-07-23 <NA>
24 2018-01-11 <NA>
25 2019-05-30 Egg;Soy;Unspecified Egg;Whole Eggs
26 2020-02-20 Chocolate;Peanut;Peanut Butter
27 2016-01-21 Raisin
28 2020-05-11 <NA>
29 2020-05-15 Chocolate
30 2019-08-16 <NA>
31 2020-03-28 Chocolate
32 2015-11-04 <NA>
33 2016-08-21 <NA>
34 2015-08-25 Almond;Coconut
35 2016-12-18 Almond
36 2016-01-18 <NA>
37 2015-11-18 Peanut;Peanut Butter
38 2019-06-04 <NA>
39 2016-04-08 <NA>
【问题讨论】:
-
什么是kip,好像在循环迭代过程中不会改变,如果正确的话,可以将
cond_2 = df[f'{kip}'].notna()提取出循环 -
cond_3 和 cond_4 也可以独立于 val 循环完成并存储结果
-
另外请添加您的数据外观和预期输出,这将有助于设计更快的替代方案
-
{kip} 是用户输入的列名(可以对数据框的多个列执行相同的操作),因此可以将其视为常规列名。我已经添加了数据片段——关于你的其他观点;我会尝试将 cond_2、3 &4 移出循环 - 实际上这是一个好点
标签: python pandas dataframe filter