iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Pandas数据处理加速技巧汇总
  • 633
分享到

Pandas数据处理加速技巧汇总

2024-04-02 19:04:59 633人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录数据准备日期时间数据优化数据的简单循环循环 .itertuples() 和 .iterrows() 方法.apply() 方法.isin() 数据选择.cut() 数据分箱Num

pandas 处理数据的效率还是很优秀的,相对于大规模的数据集只要掌握好正确的方法,就能让在数据处理时间上节省很多很多的时间。

Pandas 是建立在 NumPy 数组结构之上的,许多操作都是在 C 中执行的,要么通过 NumPy,要么通过 Pandas 自己的 python 扩展模块库,这些模块用 Cython 编写并编译为 C。理论上来说处理速度应该是很快的。

那么为什么同样一份数据由2个人处理,在设备相同的情况下处理时间会出现天差地别呢?

需要明确的是,这不是关于如何过度优化 Pandas 代码的指南。如果使用得当 Pandas 已经构建为可以快速运行。此外优化和编写干净的代码之间存在很大差异。

这是以 Python 方式使用 Pandas 以充分利用其强大且易于使用的内置功能的指南。

数据准备

此示例的目标是应用分时能源关税来计算一年的能源消耗总成本。 也就是说,在一天中的不同时间,电价会有所不同,因此任务是将每小时消耗的电量乘以消耗该小时的正确价格。

从一个包含两列的 CSV 文件中读取数据,一列用于日期加时间,另一列用于以千瓦时 (kWh) 为单位消耗的电能。

日期时间数据优化

import pandas as pd
df = pd.read_csv('数据科学必备Pandas实操数据处理加速技巧汇总/demand_profile.csv')
df.head()
     date_time  energy_kwh
0  1/1/13 0:00       0.586
1  1/1/13 1:00       0.580
2  1/1/13 2:00       0.572
3  1/1/13 3:00       0.596
4  1/1/13 4:00       0.592

乍一看这看起来不错,但有一个小问题。 Pandas 和 NumPy 有一个 dtypes(数据类型)的概念。 如果未指定任何参数,则 date_time 将采用 object dtype。

df.dtypes
date_time      object
energy_kwh    float64
dtype: object

type(df.iat[0, 0])
str

object 不仅是 str 的容器,而且是任何不能完全适合一种数据类型的列的容器。将日期作为字符串处理会既费力又低效(这也会导致内存效率低下)。为了处理时间序列数据,需要将 date_time 列格式化为日期时间对象数组( Timestamp)。

df['date_time'] = pd.to_datetime(df['date_time'])
df['date_time'].dtype
datetime64[ns]

现在有一个名为 df 的 DataFrame,有两列和一个用于引用行的数字索引

df.head()
               date_time    energy_kwh
0    2013-01-01 00:00:00         0.586
1    2013-01-01 01:00:00         0.580
2    2013-01-01 02:00:00         0.572
3    2013-01-01 03:00:00         0.596
4    2013-01-01 04:00:00         0.592

使用 Jupyter 自带的 %%time 计时装饰器进行测试

def convert(df, column_name):
	return pd.to_datetime(df[column_name])

%%time
df['date_time'] = convert(df, 'date_time')

Wall time: 663 ms

def convert_with_fORMat(df, column_name):
	return pd.to_datetime(df[column_name],format='%d/%m/%y %H:%M')

%%time
df['date_time'] = convert(df, 'date_time')

Wall time: 1.99 ms

处理效率提高将近350倍。如果在处理大规模数据的情况下,处理数据的时间会无限的放大。

数据的简单循环

既然日期和时间格式处理完毕,就可以着手计算电费了。成本因小时而异,因此需要有条件地将成本因素应用于一天中的每个小时。

在此示例中,使用时间成本将定义成三个部分。

data_type = {
    # 高峰
    "Peak":{"Cents per kWh":28,"Time Range":"17:00 to 24:00"},
    # 正常时段
    "Shoulder":{"Cents per kWh":20,"Time Range":"7:00 to 17:00"},
    # 非高峰
    "Off-Peak":{"Cents per kWh":12,"Time Range":"0:00 to 7:00"}, 
}

如果价格是一天中每小时每千瓦时 28 美分。

df['cost_cents'] = df['energy_kwh'] * 28

               date_time    energy_kwh       cost_cents
0    2013-01-01 00:00:00         0.586           16.408
1    2013-01-01 01:00:00         0.580           16.240
2    2013-01-01 02:00:00         0.572           16.016
3    2013-01-01 03:00:00         0.596           16.688
4    2013-01-01 04:00:00         0.592           16.576
...

但是成本计算取决于一天中的不同时间。这就是你会看到很多人以意想不到的方式使用 Pandas 的地方,通过编写一个循环来进行条件计算。

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'无效时间: {hour}')
    return rate * kwh

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'无效时间: {hour}')
    return rate * kwh

def apply_tariff_loop(df):
    energy_cost_list = []
    for i in range(len(df)):
    	# 循环数据直接修改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

Wall time: 2.59 s

循环 .itertuples() 和 .iterrows() 方法

Pandas 实际上 for i in range(len(df)) 通过引入 DataFrame.itertuples() 和 DataFrame.iterrows() 方法使语法就可能显得多余,这些都是yield一次一行的生成器方法。

.itertuples() 为每一行生成一个命名元组,行的索引值作为元组的第一个元素。 名称元组是来自 Python 集合模块的数据结构,其行为类似于 Python 元组,但具有可通过属性查找访问的字段。

.iterrows() 为 DataFrame 中的每一行生成 (index, Series) 对(元组)。

def apply_tariff_iterrows(df):
    energy_cost_list = []
    for index, row in df.iterrows():
        energy_used = row['energy_kwh']
        hour = row['date_time'].hour
        energy_cost = apply_tariff(energy_used, hour)
        energy_cost_list.append(energy_cost)
    df['cost_cents'] = energy_cost_list

%%time
apply_tariff_iterrows(df)

Wall time: 808 ms

速度提高又3倍之多。

.apply() 方法

可以使用 .apply() 方法进一步改进此操作。 Pandas 的 .apply() 方法采用函数(可调用对象)并将它们沿 DataFrame 的轴(所有行或所有列)应用。

lambda 函数将两列数据传递给 apply_tariff()。

def apply_tariff_withapply(df):
    df['cost_cents'] = df.apply(
        lambda row: apply_tariff(
            kwh=row['energy_kwh'],
            hour=row['date_time'].hour),
        axis=1)

%%time
apply_tariff_withapply(df)

Wall time: 181 ms

.apply() 的语法优势很明显,代码简洁、易读、明确。在这种情况下所用时间大约是该 .iterrows() 方法的4分之一。

.isin() 数据选择

但是如何在 Pandas 中将条件计算应用为矢量化操作呢?一个技巧是根据的条件选择和分组 DataFrame 的部分,然后对每个选定的组应用矢量化操作。

使用 Pandas 的.isin()方法选择行,然后在矢量化操作中应用。在执行此操作之前,如果将 date_time 列设置为 DataFrame 的索引会更方便。

df.set_index('date_time', inplace=True)

def apply_tariff_isin(df):
    peak_hours = df.index.hour.isin(range(17, 24))
    shoulder_hours = df.index.hour.isin(range(7, 17))
    off_peak_hours = df.index.hour.isin(range(0, 7))

    df.loc[peak_hours, 'cost_cents'] = df.loc[peak_hours, 'energy_kwh'] * 28
    df.loc[shoulder_hours,'cost_cents'] = df.loc[shoulder_hours, 'energy_kwh'] * 20
    df.loc[off_peak_hours,'cost_cents'] = df.loc[off_peak_hours, 'energy_kwh'] * 12

%%time
apply_tariff_isin(df)

Wall time: 53.5 ms

其中整个过程方法返回一个布尔列表。

[False, False, False, ..., True, True, True]

.cut() 数据分箱

设置时间切分的列表和对那个计算的函数公式,让操作起来更简单,但是这个对于新手来说代码阅读起来有些困难。

def apply_tariff_cut(df):
    cents_per_kwh = pd.cut(x=df.index.hour,
                           bins=[0, 7, 17, 24],
                           include_lowest=True,
                           labels=[12, 20, 28]).astype(int)
    df['cost_cents'] = cents_per_kwh * df['energy_kwh']
    
%%time
apply_tariff_cut(df)

Wall time: 2.99 ms

Numpy 方法处理

Pandas Series 和 DataFrames 是在 NumPy 库之上设计的。这为提供了更大的计算灵活性,因为 Pandas 可以与 NumPy 数组和操作无缝协作。

使用 NumPy 的digitize()函数。它与 Pandas 的相似之处cut()在于数据将被分箱,但这次它将由一个索引数组表示,该数组表示每个小时属于哪个箱。然后将这些索引应用于价格数组。

import numpy as np

def apply_tariff_digitize(df):
    prices = np.array([12, 20, 28])
    bins = np.digitize(df.index.hour.values, bins=[7, 17, 24])
    df['cost_cents'] = prices[bins] * df['energy_kwh'].values

%%time
apply_tariff_digitize(df)

Wall time: 1.99 ms

处理效率比较

对比一下上面几种不同的处理方式的效率吧。

功能运行时间(秒)
apply_tariff_loop()2.59 s
apply_tariff_iterrows()808 ms
apply_tariff_withapply()181 ms
apply_tariff_isin()53.5 ms
apply_tariff_cut()2.99 ms
apply_tariff_digitize()1.99 ms

HDFStore 防止重新处理

通常构建复杂的数据模型时,对数据进行一些预处理会很方便。如果有 10 年的分钟频率用电量数据,即指定了格式参数简单地将日期和时间转换为日期时间也可能需要 20 分钟。只需要这样做一次而不是每次运行模型时都需要进行测试或分析。

可以在这里做的一件非常有用的事情是预处理,然后以处理后的形式存储数据,以便在需要时使用。但是如何才能以正确的格式存储数据而无需再次重新处理呢?如果要保存为 CSV 只会丢失您的日期时间对象,并且在再次访问时必须重新处理它。

Pandas 有一个内置的解决方案使用 HDF5,一种专为存储表格数据数组而设计的高性能存储格式。Pandas 的 HDFStore 类允许将 DataFrame 存储在 HDF5 文件中,以便可以有效地访问它,同时仍保留列类型和其他元数据。dict 是一个类似字典的类,因此可以像对 Python对象一样进行读写。

将预处理的耗电量 DataFrame 存储df在 HDF5 文件中。

data_store = pd.HDFStore('processed_data.h5')

# 将 DataFrame 放入对象中,将键设置为 preprocessed_df 
data_store['preprocessed_df'] = df
data_store.close()

从 HDF5 文件访问数据的方法,并保留数据类型。

data_store = pd.HDFStore('processed_data.h5')

preprocessed_df = data_store['preprocessed_df']
data_store.close()

到此这篇关于Pandas数据处理加速技巧汇总的文章就介绍到这了,更多相关Pandas数据处理内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Pandas数据处理加速技巧汇总

本文链接: https://www.lsjlt.com/news/117369.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Pandas数据处理加速技巧汇总
    目录数据准备日期时间数据优化数据的简单循环循环 .itertuples() 和 .iterrows() 方法.apply() 方法.isin() 数据选择.cut() 数据分箱Num...
    99+
    2022-11-10
  • python数据分析必会的Pandas技巧汇总
    目录一、Pandas两大数据结构的创建二、DataFrame常见方法三、数据索引四、DataFrame选取和重新组合数据的方法五、排序六、相关分析和统计分析七、分组的方法八、读写文本...
    99+
    2022-11-12
  • Pandas 缺失数据处理代码汇总
    目录一、缺失值类型1、np.nan2、None3、NA标量二、缺失值判断1、对整个dataframe判断缺失2、对某个列判断缺失三、缺失值统计1、列缺失2、行缺失3、缺失率四、缺失值...
    99+
    2022-11-12
  • Pandas提高数据分析效率的13个技巧汇总
    目录1.计算变量缺失率2.获取分组里最大值所在的行方法3.多列合并为一行4.删除包含特定字符串所在的行5.组内排序6.选择特定类型的列7.字符串转换为数值8.优化 DataFrame...
    99+
    2022-11-11
  • Python数据处理的26个Pandas实用技巧总结
    目录从剪贴板中创建DataFram将DataFrame划分为两个随机的子集多种类型过滤DataFrameDataFrame筛选数量最多类别处理缺失值一个字符串划分成多列Series扩...
    99+
    2022-11-13
  • Pandas中Apply函数加速百倍的技巧分享
    目录前言实验对比01 Apply(Baseline)02 Swift加速03 向量化04 类别转化+向量化05 转化为values处理实验汇总前言 虽然目前dask,cudf等包的出...
    99+
    2022-11-11
  • Java 8 Stream 处理数据方法汇总
    目录Stream流Stream流是什么,为什么要用它Stream流的基础使用简单综合案例传统方法Stream流式处理方法获取流根据Collection获取流根据Map获取流根据数组获...
    99+
    2022-11-13
  • Pandas 多进程处理数据提高速度
    目录1、单进程2、多进程前言: python 有自己的多进包 multiprocessing 去实现并行计算,但在Pandas处理数据中,使用 multiprocessing 并不好...
    99+
    2022-11-10
  • python数据处理67个pandas函数总结看完就用
    目录导⼊数据导出数据查看数据数据选取数据处理数据分组、排序、透视数据合并不管是业务数据分析 ,还是数据建模。数据处理都是及其重要的一个步骤,它对于最终的结果来说,至关重...
    99+
    2022-11-12
  • Golang数据处理技巧大揭秘
    Golang数据处理技巧大揭秘,需要具体代码示例引言:Golang作为一种高效且强大的编程语言,广泛应用于数据处理领域。本文将分享一些Golang中常用的数据处理技巧,并给出具体的代码示例,旨在帮助读者更好地理解和运用这些技巧。一、使用切片...
    99+
    2023-12-23
    Golang (Go语言) 数据处理 (data processing) 技巧 (Techniques)
  • python pandas处理excel表格数据的常用方法总结
    目录前言1、读取xlsx表格:pd.read_excel()2、获取表格的数据大小:shape3、索引数据的方法:[ ] / loc[] / iloc[]4、判断数据为空:np.is...
    99+
    2022-11-11
  • 浅谈Pandas dataframe数据处理方法的速度比较
    数据修改主要以增删改差为主,这里比较几种写法在数据处理时间上的巨大差别。 数据量大概是500万行级别的数据,文件大小为100M。 1.iloc iloc是一种速度极其慢的写法。这里我...
    99+
    2022-11-12
  • 加速Python数据分析的小技巧分别有哪些
    这期内容当中小编将会给大家带来有关加速Python数据分析的小技巧分别有哪些,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。有时候,一点小小的黑客行为可以节省时间,挽救生命。一个小小的快捷方式或附加组件有时...
    99+
    2023-06-16
  • 30 个 Python 函数,加速数据分析处理速度
    目录1.删除列2.选择特定列3.nrows4.样品5.检查缺失值6.使用 loc 和 iloc 添加缺失值7.填充缺失值8.删除缺失值9.根据条件选择行10.用查询描述条件11.用 ...
    99+
    2022-11-12
  • PHP中的表格数据处理技巧
    在网站的开发中,表格是一个常见的元素,用于展示数据、进行数据录入和数据处理等。而在PHP中,对表格数据的处理也是比较常见的操作。在本文中,我们将介绍一些常用的PHP表格数据处理技巧。从表单获取数据在PHP中,表单数据可以通过$_POST或$...
    99+
    2023-05-25
    PHP表格处理 数据处理技巧 表格数据处理
  • Excel数据导入Mysql常见问题汇总:如何处理导入速度过慢的问题?
    Excel数据导入MySQL是日常数据处理中常见的操作之一,但在实际操作中常会遇到导入速度过慢的问题。导入速度过慢会导致数据处理的效率降低,影响工作进程。本文将介绍一些解决导入速度过慢问题的方法,以帮助读者解决这一问题。首先,导入速度过慢的...
    99+
    2023-10-22
    MySQL 问题处理 导入速度
  • 处理大数据:Python日志存储技巧
    在当今信息时代,数据已经成为了企业最重要的资源之一。随着技术的不断发展,数据的存储和处理也变得越来越方便。Python作为一种流行的编程语言,可以帮助我们处理大量的数据。在本文中,我们将介绍Python中的日志存储技巧,以便更有效地处理大...
    99+
    2023-06-19
    日志 存储 大数据
  • Python数据预处理常用的5个技巧
    目录前言数据集示例 1示例 2示例 3示例 4示例 5总结前言 我们知道数据是一项宝贵的资产,近年来经历了指数级增长。但是原始数据通常不能立即使用,它需要进行大量清理和转换。 Pan...
    99+
    2022-11-13
  • Python数据处理的实用技巧有哪些
    今天小编给大家分享一下Python数据处理的实用技巧有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。我使用的 Panda...
    99+
    2023-06-29
  • PHP 中的实时文件操作技巧:如何使用数组快速处理数据?
    PHP 是一种广泛使用的脚本语言,尤其在 Web 开发中。在处理数据时,PHP 提供了许多内置函数和方法,但有时候我们需要对文件进行实时操作来快速处理数据。在这篇文章中,我们将介绍一些 PHP 中的实时文件操作技巧,以及如何使用数组来快速处...
    99+
    2023-09-01
    文件 数组 实时
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作