使用Pandas和SQL高效重构长格式数据为列表型数组

使用pandas和sql高效重构长格式数据为列表型数组

本文探讨了如何将从SQL数据库中获取的长格式数据(Time, QuantityMeasured, Value)高效重构为Pandas中的宽格式列表型数组。文章对比了多种Python和Pandas处理方法,并提出了一种优化的Pandas策略,即先筛选再透视,以减少处理的数据量。此外,还介绍了将数据重构逻辑下推到SQL数据库执行的方案,这通常能带来显著的性能提升,尤其适用于大规模数据集。

数据重构需求与挑战

在数据分析和处理中,我们经常会遇到从关系型数据库(如MySQL)中提取数据,并需要将其从“长格式”(long format)转换为“宽格式”(wide format)的情况。例如,原始数据可能包含时间戳、测量类型和测量值,结构如下:

        Time    QuantityMeasured       Value0       t1          A                       71       t1          B                       22       t1          C                       83       t1          D                       94       t1          E                       5...     ...         ...                     ...18482   tn          A                       518483   tn          C                       318484   tn          E                       418485   tn          B                       518486   tn          D                       1

而最终目标是将其转换为独立的Python列表或NumPy数组,每个列表对应一种测量类型,例如:

list_of_time = ['t1', ..., 'tn']list_of_A    = [7, ..., 5]list_of_B    = [2, ..., 5]list_of_C    = [8, ..., 3]list_of_D    = [9, ..., 8]

这种转换在处理来自传感器、日志或金融交易等多种时间序列数据时尤为常见。挑战在于如何高效地完成这一转换,尤其是在数据量较大时。

Pandas数据重构策略

Pandas库提供了强大的数据处理能力,是Python中进行数据重构的首选工具

1. 基础透视(Pivot)操作

最直观的方法是使用pivot函数将长格式数据转换为宽格式。

import pandas as pd# 假设df是您的原始DataFrame# df = pd.read_sql("SELECT Time, QuantityMeasured, Value FROM your_table", your_sql_connection)# 示例数据data = {    'Time': ['t1', 't1', 't1', 't1', 't1', 'tn', 'tn', 'tn', 'tn', 'tn'],    'QuantityMeasured': ['A', 'B', 'C', 'D', 'E', 'A', 'C', 'E', 'B', 'D'],    'Value': [7, 2, 8, 9, 5, 5, 3, 4, 5, 1]}df = pd.DataFrame(data)pivot_df = df.pivot(index='Time', columns='QuantityMeasured', values='Value')# 提取所需列表time = pivot_df.index.tolist()list_of_A = pivot_df['A'].tolist()list_of_B = pivot_df['B'].tolist()list_of_C = pivot_df['C'].tolist()list_of_D = pivot_df['D'].tolist()print("Pivot DataFrame:n", pivot_df)print("nlist_of_A:", list_of_A)

这种方法虽然简洁,但如果QuantityMeasured列包含大量不需要的类别,pivot操作会创建一个非常宽的DataFrame,其中包含许多空值(NaN),这会增加内存消耗和计算时间。

2. 优化:先筛选后透视

为了提高效率,尤其是当只需要部分QuantityMeasured类别时,应在透视之前进行数据筛选。这可以显著减少透视操作的数据量。

# 筛选出我们需要的'A', 'B', 'C', 'D'类别agg_df = (    df.query("QuantityMeasured in ['A', 'B', 'C', 'D']")    .pivot(index='Time', columns='QuantityMeasured', values='Value'))# 提取所需列表time = agg_df.index.tolist()list_of_A = agg_df['A'].tolist()list_of_B = agg_df['B'].tolist()list_of_C = agg_df['C'].tolist()list_of_D = agg_df['D'].tolist()print("nOptimized Pivot DataFrame:n", agg_df)print("nlist_of_A (optimized):", list_of_A)

这种方法通过query函数提前过滤掉不相关的行,使得pivot操作在更小的数据集上进行,从而提高了性能。

3. 替代透视方法:set_index与unstack

pivot函数在底层通常会调用set_index和unstack。在某些情况下,直接使用这两个函数可能会略微更快,因为它提供了更细粒度的控制。

agg_df_unstack = (    df    .query("QuantityMeasured in ['A', 'B', 'C', 'D']")    .set_index(['Time', 'QuantityMeasured'])['Value']    .unstack())# 提取所需列表time_unstack = agg_df_unstack.index.tolist()list_of_A_unstack = agg_df_unstack['A'].tolist()list_of_B_unstack = agg_df_unstack['B'].tolist()list_of_C_unstack = agg_df_unstack['C'].tolist()list_of_D_unstack = agg_df_unstack['D'].tolist()print("nUnstack DataFrame:n", agg_df_unstack)print("nlist_of_A (unstack):", list_of_A_unstack)

这两种Pandas优化方法在处理约1.8万行数据时,可以将处理时间从0.18-0.22秒缩短到0.03秒左右,这是一个显著的提升。然而,要达到数量级(例如0.002秒)的性能提升,在Python/Pandas层面通常很难实现,因为这已经接近了Python数据结构操作的性能极限。

SQL端数据重构:将逻辑下推至数据库

对于大规模数据集或对性能有极高要求的情况,最有效的策略是将数据重构的逻辑下推到数据库层面执行。SQL数据库在处理聚合和透视操作方面通常比Python/Pandas更高效,因为它们是为这类操作而优化的。

通过在SQL查询中使用CASE WHEN语句和GROUP BY子句,可以在数据被拉取到Python之前就完成透视操作。

SELECT  Time,  SUM(CASE WHEN QuantityMeasured = 'A' THEN Value ELSE NULL END) AS A,  SUM(CASE WHEN QuantityMeasured = 'B' THEN Value ELSE NULL END) AS B,  SUM(CASE WHEN QuantityMeasured = 'C' THEN Value ELSE NULL END) AS C,  SUM(CASE WHEN QuantityMeasured = 'D' THEN Value ELSE NULL END) AS DFROM your_table_name  -- 替换为您的实际表名WHERE QuantityMeasured IN ('A', 'B', 'C', 'D') -- 提前过滤,减少聚合数据量GROUP BY TimeORDER BY Time; -- 确保时间顺序一致

说明:

SUM(CASE WHEN … THEN … ELSE NULL END):对于每个Time组,CASE WHEN会检查QuantityMeasured是否匹配特定类别。如果匹配,则取Value;否则,取NULL。SUM函数会忽略NULL值,从而有效地为每个类别生成一个聚合值。如果一个Time只有一个QuantityMeasured对应一个Value,SUM在这里就起到了选择该Value的作用。如果存在多个相同Time和QuantityMeasured的记录,SUM会将它们加起来,这可能需要根据实际业务逻辑调整(例如使用MAX或MIN)。WHERE QuantityMeasured IN (‘A’, ‘B’, ‘C’, ‘D’):在聚合之前进行过滤,只处理我们需要的测量类型,这与Pandas中的query操作类似,能大幅提高SQL查询的效率。GROUP BY Time:按照时间戳进行分组,为每个时间戳生成一行包含所有所需测量类型的值。ORDER BY Time:确保结果按时间顺序排列,这对于生成时间序列列表非常重要。

执行这样的SQL查询后,您将直接从数据库获得一个宽格式的结果集,然后可以轻松地将其加载到Pandas DataFrame中,并进一步提取为独立的Python列表。

# 假设conn是您的SQL连接对象# sql_query = """# SELECT#   Time,#   SUM(CASE WHEN QuantityMeasured = 'A' THEN Value ELSE NULL END) AS A,#   SUM(CASE WHEN QuantityMeasured = 'B' THEN Value ELSE NULL END) AS B,#   SUM(CASE WHEN QuantityMeasured = 'C' THEN Value ELSE NULL END) AS C,#   SUM(CASE WHEN QuantityMeasured = 'D' THEN Value ELSE NULL END) AS D# FROM your_table_name# WHERE QuantityMeasured IN ('A', 'B', 'C', 'D')# GROUP BY Time# ORDER BY Time;# """## pivoted_df_from_sql = pd.read_sql(sql_query, conn)## time_sql = pivoted_df_from_sql['Time'].tolist()# list_of_A_sql = pivoted_df_from_sql['A'].tolist()# list_of_B_sql = pivoted_df_from_sql['B'].tolist()# list_of_C_sql = pivoted_df_from_sql['C'].tolist()# list_of_D_sql = pivoted_df_from_sql['D'].tolist()## print("nData from SQL Pivot:n", pivoted_df_from_sql)

这种方法通常能提供最佳的性能,因为它利用了数据库的优化能力,减少了数据传输量和Python端的处理负担。

总结与注意事项

选择合适的工具: 对于小到中等规模的数据集,Pandas的优化透视方法(先筛选后透视)是一个很好的选择。它提供了灵活性和Python生态系统的便利。性能瓶颈 在Python/Pandas中,数据重构的性能提升往往存在瓶颈。期望达到数量级的速度提升可能不现实,尤其是在数据量较大时。数据库优先: 对于大规模数据集或对性能有严格要求的情况,将数据重构逻辑下推到SQL数据库执行通常是最佳实践。SQL查询在处理这类聚合和透视操作时效率更高。数据完整性: 在进行透视操作时,务必注意原始数据中是否存在重复的Time和QuantityMeasured组合。如果存在,pivot或unstack可能会报错,或者需要pivot_table配合聚合函数来处理。SQL的SUM或MAX等聚合函数可以自然地处理这些情况。空值处理: 透视操作后,如果某些Time没有对应的QuantityMeasured值,结果中会出现NaN。在转换为列表前,可能需要进行空值填充或删除。

通过理解这些不同的策略及其优缺点,您可以根据具体的项目需求和数据规模,选择最适合的高效数据重构方法。

以上就是使用Pandas和SQL高效重构长格式数据为列表型数组的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1377423.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月14日 17:45:49
下一篇 2025年12月14日 17:46:02

相关推荐

  • Golang如何处理依赖包冲突

    Go语言通过Go Modules解决依赖冲突,采用最小版本选择策略自动解析依赖,支持replace和require手动控制版本,并提供go mod tidy、go list等命令管理与分析依赖,结合最佳实践可有效避免冲突。 Go 语言通过 Go Modules 解决依赖包冲突问题,从 Go 1.11…

    2025年12月16日
    000
  • 如何在Golang中测试缓存机制

    答案是测试Golang缓存需验证读写、过期、并发和依赖隔离。首先使用sync.Map或自定义结构测试基本存取;接着通过设置短TTL验证过期清除;再用多goroutine并发读写并运行-race检测数据竞争;最后通过接口抽象缓存,注入Mock实现隔离外部依赖,确保各行为可测可控。 在Golang中测试…

    2025年12月16日
    000
  • 如何在Windows环境搭建Golang开发环境

    答案是:在Windows上搭建Go开发环境需先下载安装Go并验证版本,配置GOPATH和PATH环境变量,推荐使用VS Code或GoLand作为编辑器并安装Go扩展,最后创建hello.go文件测试运行。整个过程简单清晰,关键在于正确设置环境变量和工具链。 在Windows系统上搭建Golang开…

    2025年12月16日
    000
  • Golang如何使用go mod tidy清理无用依赖

    go mod tidy用于清理未使用依赖、补全缺失依赖并同步go.sum文件。执行该命令会分析代码中的import,移除go.mod中无用模块,添加缺失依赖,更新版本信息,并校验go.sum完整性。常用选项包括-v(输出详情)、-compat指定兼容版本、-droprequire/-droprepl…

    2025年12月16日
    000
  • 如何在Golang中使用net包实现网络通信

    net包是Golang网络编程核心,支持TCP、UDP等协议。通过net.Listen创建TCP服务器,net.Dial实现客户端通信,使用goroutine处理并发连接;UDP则用net.ListenPacket和ResolveUDPAddr实现无连接通信;需注意地址解析、错误处理及设置读写超时,…

    2025年12月16日
    000
  • Golang如何使用sync实现并发安全

    使用sync.Mutex可确保多goroutine下对共享变量的安全访问,通过加锁解锁机制防止数据竞争;2. sync.RWMutex在读多写少场景中提升性能,允许多个读操作并发执行,写操作则独占资源;3. sync.Once保证初始化逻辑仅执行一次,适用于单例或全局初始化;4. sync.Wait…

    2025年12月16日
    000
  • Golang如何开发基础的博客平台

    答案:用Golang开发基础博客平台需搭建Web服务、设计Post数据模型、实现CRUD功能并连接数据库。1. 使用net/http注册路由如/、/post/:id,启动服务监听8080端口;2. 定义Post结构体含ID、Title、Content、CreatedAt字段,初期以全局切片存储,后期…

    2025年12月16日
    000
  • Golang如何实现CI/CD流水线

    答案:Go项目CI/CD核心是通过GitHub Actions等平台实现自动化测试、构建与部署。1. 代码提交触发流水线;2. 安装Go依赖并检查代码质量;3. 运行单元测试并生成覆盖率报告;4. 构建二进制文件或Docker镜像;5. 主分支自动部署到生产环境;6. 结合语义化版本发布与回滚机制确…

    2025年12月16日
    000
  • Golang测试表驱动与基准组合方法

    表驱动测试结合基准测试可同时验证代码正确性与性能。通过定义测试用例结构体,TestAdd函数覆盖多种输入场景,确保逻辑正确;BenchmarkConcatStrings则对不同规模字符串拼接进行性能测量,利用b.Run为每组数据单独计时,实现精细化性能监控,提升测试可维护性与执行效率。 在 Go 语…

    2025年12月16日
    000
  • Golang如何优化算法复杂度

    优化算法复杂度需从数据结构、逻辑、并发和语言特性入手:①选用map、slice等合适结构;②通过双指针、记忆化、剪枝降低冗余计算;③利用goroutine并行处理独立任务;④避免频繁内存分配、字符串拼接等性能陷阱,结合Go特性在时间、空间与可读性间平衡。 优化算法复杂度的核心在于减少时间和空间的消耗…

    2025年12月16日
    000
  • 如何在Golang中实现模块依赖隔离

    使用internal包、分层目录结构、接口抽象和go mod工作区模式,可有效实现Golang模块依赖隔离。通过internal限制包访问,按功能划分模块,各模块自包含且不直接相互引用;公共逻辑下沉至pkg,模块间通信基于接口而非实现,运行时通过依赖注入绑定具体实现;每个模块独立管理go.mod,利…

    2025年12月16日
    000
  • Go并发编程:深入理解Channel死锁与避免策略

    本文深入探讨了go语言中因channel操作不当导致的死锁问题。通过分析一个典型的代码示例,详细解释了无缓冲channel在发送与接收不匹配时如何引发死锁,并提供了有效的解决方案。文章强调了在并发编程中平衡channel读写操作的重要性,并提出了一系列避免channel死锁的通用策略,以确保go程序…

    2025年12月16日
    000
  • Go 语言中利用反射动态创建指定类型切片

    本文深入探讨了在 Go 语言中如何利用 reflect 包在运行时动态创建指定类型的切片。通过详细解析 reflect.TypeOf、reflect.SliceOf、reflect.MakeSlice 和 reflect.Zero 等核心函数,文章提供了创建空切片和 nil 切片的两种方法,并辅以代…

    2025年12月16日
    000
  • Go语言中获取与解析Web内容:HTTP请求与基础XML处理

    本教程将指导您如何在go语言中高效地进行web数据抓取,核心内容包括使用`net/http`包发送http请求获取html/xml原始数据,以及如何利用`io/ioutil`读取响应体。同时,文章还将简要介绍go标准库`encoding/xml`包进行xml数据解析的基础方法,帮助开发者快速掌握we…

    2025年12月16日
    000
  • Go语言GPIO操作指南:通用输入输出的读写实践

    本文探讨了如何使用go语言进行通用输入输出(gpio)操作,特别指出`davecheney/gpio`包是实现这一功能的重要工具。该包提供了用户空间接口来控制gpio引脚,并通过`rpi`子包为树莓派等特定硬件提供了优化支持,使得go开发者能够高效地与硬件交互,实现对硬件设备的编程控制。 Go语言与…

    2025年12月16日
    000
  • Go语言HMAC实践:安全签名生成、验证与hmac.Equal未定义错误解析

    本教程深入探讨go语言中基于hmac的消息认证码实现,涵盖如何安全地生成和验证数据签名。文章将详细介绍`crypto/hmac`包的使用,包括`hmac.new`、`hmac.write`、`hmac.sum`以及关键的`hmac.equal`函数。针对常见的“`hmac.equal`未定义”错误,…

    2025年12月16日
    000
  • 如何在Golang中实现多线程错误汇总

    使用channel和WaitGroup可安全汇总goroutine错误,示例中通过带缓冲的error channel收集各任务错误,wg确保等待所有协程完成,最后遍历channel获取全部错误;若用errgroup则更简洁,但需注意返回nil以避免提前终止。 在Golang中,”多线程&…

    2025年12月16日
    000
  • Golang如何使用mock对象进行单元测试

    Go语言通过接口抽象和mock工具实现依赖隔离测试。首先定义UserRepository接口并创建UserService结构体依赖该接口,接着手动实现MockUserRepository结构体模拟数据返回,在测试中替换真实数据库调用;对于复杂场景可使用testify/mock库,通过On(&#822…

    2025年12月16日
    000
  • 如何在Golang中使用测试覆盖率工具

    使用go test -cover生成测试覆盖率,结合-coverprofile输出数据文件,再用go tool cover -html可视化,可直观查看代码覆盖情况,绿色为已覆盖,红色为未覆盖,支持设置阈值和持续集成检查。 在Golang中使用测试覆盖率工具可以帮助你了解代码中哪些部分被测试覆盖,哪…

    2025年12月16日
    000
  • Go 语言中实现跨平台条件编译:深入理解构建约束与文件命名约定

    go 语言通过构建约束(build constraints)和特定的文件命名约定,提供了强大的跨平台条件编译能力。本文将详细介绍如何利用 `// +build` 指令定义编译标签,以及如何通过 `*_goos` 和 `*_goarch` 等文件命名模式,在不同操作系统、架构或特定条件下选择性地包含或…

    2025年12月16日
    000

发表回复

登录后才能评论
关注微信