1.61s,看上去挺快,但其实可以更快,我们来看一下下面的方法。
- >>> @timeit(repeat=3, number=100)
- >>> def convert_with_format(df, column_name):
- ... return pd.to_datetime(df[column_name],
- ... format='%d/%m/%y %H:%M')
- Best of 3 trials with 100 function calls per trial:
- Function `convert_with_format` ran in average of 0.032 seconds.
结果只有0.032s,快了将近50倍。原因是:我们设置了转化的格式format。由于在CSV中的datetimes并不是 ISO 8601 格式的,如果不进行设置的话,那么pandas将使用 dateutil 包把每个字符串str转化成date日期。
相反,如果原始数据datetime已经是 ISO 8601 格式了,那么pandas就可以立即使用最快速的方法来解析日期。这也就是为什么提前设置好格式format可以提升这么多。
pandas数据的循环操作
仍然基于上面的数据,我们想添加一个新的特征,但这个新的特征是基于一些时间条件的,根据时长(小时)而变化,如下:

因此,按照我们正常的做法就是使用apply方法写一个函数,函数里面写好时间条件的逻辑代码。
- def apply_tariff(kwh, hour):
- """计算每个小时的电费"""
- if 0 <= hour < 7:
- rate = 12
- elif 7 <= hour < 17:
- rate = 20
- elif 17 <= hour < 24:
- rate = 28
- else:
- raise ValueError(f'Invalid hour: {hour}')
- return rate * kwh
然后使用for循环来遍历df,根据apply函数逻辑添加新的特征,如下:
- >>> # 不赞同这种操作
- >>> @timeit(repeat=3, number=100)
- ... def apply_tariff_loop(df):
- ... """Calculate costs in loop. Modifies `df` inplace."""
- ... energy_cost_list = []
- ... for i in range(len(df)):
- ... # 获取用电量和时间(小时)
- ... energy_used = df.iloc[i]['energy_kwh']
- ... hour = df.iloc[i]['date_time'].hour
- ... energy_cost = apply_tariff(energy_used, hour)
- ... energy_cost_list.append(energy_cost)
- ... df['cost_cents'] = energy_cost_list
- ...
- >>> apply_tariff_loop(df)
- Best of 3 trials with 100 function calls per trial:
- Function `apply_tariff_loop` ran in average of 3.152 seconds.
对于那些写Pythonic风格的人来说,这个设计看起来很自然。然而,这个循环将会严重影响效率,也是不赞同这么做。原因有几个:
- 首先,它需要初始化一个将记录输出的列表。
- 其次,它使用不透明对象范围(0,len(df))循环,然后在应用apply_tariff()之后,它必须将结果附加到用于创建新DataFrame列的列表中。它还使用df.iloc [i] ['date_time']执行所谓的链式索引,这通常会导致意外的结果。
- 但这种方法的最大问题是计算的时间成本。对于8760行数据,此循环花费了3秒钟。接下来,你将看到一些改进的Pandas结构迭代解决方案。
使用itertuples() 和iterrows() 循环
那么推荐做法是什么样的呢?
实际上可以通过pandas引入itertuples和iterrows方法可以使效率更快。这些都是一次产生一行的生成器方法,类似scrapy中使用的yield用法。
.itertuples为每一行产生一个namedtuple,并且行的索引值作为元组的第一个元素。nametuple是Python的collections模块中的一种数据结构,其行为类似于Python元组,但具有可通过属性查找访问的字段。
.iterrows为DataFrame中的每一行产生(index,series)这样的元组。 (编辑:源码网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|