利用Pandas和NumPy高效从索引映射生成坐标DataFrame

利用Pandas和NumPy高效从索引映射生成坐标DataFrame

本文详细介绍了如何根据一个索引列表,从现有pandas dataframe中高效提取对应的x、y坐标,并构建一个新的dataframe。文章首先探讨了基于循环和字典的初步实现方式及其改进,随后重点展示了利用numpy进行矢量化操作的优化方案,该方案显著提升了数据处理性能,为后续的数据可视化和分析奠定了坚实基础。

从索引映射构建坐标DataFrame教程

在数据处理和分析中,我们经常需要根据特定的映射规则从一个数据集中提取信息并重构为新的数据结构。本教程将聚焦于一个常见场景:给定一个包含索引对的列表和一个包含坐标信息的Pandas DataFrame,目标是创建一个新的DataFrame,其中每一行代表一个由索引对指向的X、Y坐标。

1. 问题描述与原始数据

假设我们拥有以下两组数据:

tours: 一个列表的列表(list of lists),其中每个子列表包含两个整数。第一个整数代表原始DataFrame中X坐标的行索引,第二个整数代表Y坐标的行索引。df: 一个Pandas DataFrame,包含多列数据,其中包括 Node、X、Y、Demand 和 Profit。

我们的任务是创建一个名为 coord 的新DataFrame,它只有 X 和 Y 两列。coord 的每一行都应根据 tours 中的索引对,从 df 中查找对应的X和Y值。

示例原始数据:

import pandas as pdimport numpy as nptours = [[0, 4], [0, 5], [0, 6], [1, 13], [2, 0], [3, 8], [4, 9], [5, 10],         [6, 7], [7, 1], [8, 2], [9, 3], [10, 11], [11, 14], [12, 0], [13, 12], [14, 0]]data = {    'Node': [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],    'X': [5.7735, 2.8867, -2.8868, -5.7735, -2.8867, 2.8868, 8.6603, 0.0000, -8.6603, -8.6603, 0.0000, 8.6603, 5.3405, 3.3198, 6.4952],    'Y': [0.00, 5.00, 5.00, 0.00, -5.00, -5.00, 5.00, 10.00, 5.00, -5.00, -10.00, -5.00, 0.75, 4.25, -1.25],    'Demand': [40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 10.0, 10.0, 10.0],    'Profit': [16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 24.0, 24.0, 24.0, 24.0, 24.0, 10.0, 10.0, 11.0]}df = pd.DataFrame(data, index=range(len(data['Node']))) # 确保df的索引从0开始,与tours中的索引匹配

理解 tours 的含义:tours 中的 [0, 4] 表示:

X坐标取自 df.iloc[0][‘X’]Y坐标取自 df.iloc[4][‘Y’]

2. 方法一:基于循环和字典的构建

一种直观的方法是遍历 tours 列表,在每次迭代中根据索引从 df 中提取X和Y值,并将它们存储在一个字典中,最后将字典转换为DataFrame。

2.1 初步尝试与问题

最初的尝试可能如下:

d = {}for t, tour in enumerate(tours):    xi = tour[0]    yi = tour[1]    key = t    d[key] = df["X"].iloc[xi], df["Y"].iloc[yi]# 尝试直接使用pd.DataFrame(d.items(), columns=['X', 'Y'])# 这将导致错误或不符合预期的结果,因为d.items()会把键作为第一列,值(元组)作为第二列

这种方法在将字典 d 转换为DataFrame时会遇到问题。pd.DataFrame(d.items(), columns=[‘X’, ‘Y’]) 会将字典的键作为第一列(在这里是索引 0, 1, 2…),而将值(一个包含X和Y的元组)作为第二列。这并不是我们期望的两列 X 和 Y。

2.2 改进后的字典方法

为了正确地将字典转换为DataFrame,其中字典的键作为DataFrame的索引,而字典的值(元组)拆分为多列,我们需要使用 pd.DataFrame.from_dict() 方法,并设置 orient=’index’ 参数。

d = {}for t, tour in enumerate(tours):    xi = tour[0] # 获取X坐标的索引    yi = tour[1] # 获取Y坐标的索引    # 根据索引从df中查找对应的X和Y值    x_val = df["X"].iloc[xi]    y_val = df["Y"].iloc[yi]    d[t] = (x_val, y_val) # 将(X, Y)元组作为字典的值# 使用from_dict并指定orient='index'来正确构建DataFramecoord_loop = pd.DataFrame.from_dict(d, orient='index', columns=['X', 'Y'])print("方法一(循环+字典)结果:")print(coord_loop.head())

优点:

逻辑清晰,易于理解,适合初学者。在数据量较小的情况下表现尚可。

缺点:

使用Python循环遍历Pandas Series,效率较低,尤其是在处理大型数据集时。需要额外创建字典作为中间数据结构。

3. 方法二:利用NumPy进行矢量化优化 (推荐)

对于Pandas和NumPy而言,矢量化操作通常比Python循环具有更高的性能。我们可以将 tours 转换为NumPy数组,并将 df 中的X、Y列提取为NumPy数组,然后利用NumPy的高级索引功能一步到位地获取所有坐标。

3.1 核心思想

将 tours 转换为NumPy数组,这样可以方便地通过 tours[:, 0] 获取所有X索引,通过 tours[:, 1] 获取所有Y索引。将 df 的 X 和 Y 列提取为一个NumPy数组,这样可以方便地通过索引直接访问这些值。利用NumPy的广播和高级索引特性,一次性从 df 的X、Y数组中提取所有需要的坐标。

3.2 实现步骤

# 1. 将tours列表转换为NumPy数组tours_np = np.array(tours)# 2. 从df中提取X和Y列,并转换为NumPy数组# 这样arr[index, 0] 对应X值,arr[index, 1] 对应Y值df_coords_np = df[["X", "Y"]].to_numpy()# 3. 使用高级索引一次性获取所有X和Y坐标# tours_np[:, 0] 提供了所有X坐标的索引# tours_np[:, 1] 提供了所有Y坐标的索引extracted_x = df_coords_np[tours_np[:, 0], 0] # 获取所有X坐标extracted_y = df_coords_np[tours_np[:, 1], 1] # 获取所有Y坐标# 4. 构建最终的DataFramecoord_vectorized = pd.DataFrame({"X": extracted_x, "Y": extracted_y})print("n方法二(NumPy矢量化)结果:")print(coord_vectorized.head())

代码解释:

tours_np = np.array(tours): 将 tours 转换为一个 (n, 2) 形状的NumPy数组。df_coords_np = df[[“X”, “Y”]].to_numpy(): 从 df 中选择 X 和 Y 列,并将其转换为一个NumPy数组。这个数组的行索引与原始 df 的行索引一致,第一列是 X 值,第二列是 Y 值。tours_np[:, 0]:这会选择 tours_np 数组的所有行,并获取每行的第一个元素(即X坐标的索引)。tours_np[:, 1]:这会选择 tours_np 数组的所有行,并获取每行的第二个元素(即Y坐标的索引)。df_coords_np[tours_np[:, 0], 0]: 这是一个高级索引操作。它使用 tours_np[:, 0] 作为行索引,从 df_coords_np 中选择对应的行,然后从这些行中选择第0列(即X坐标)。df_coords_np[tours_np[:, 1], 1]: 同样,它使用 tours_np[:, 1] 作为行索引,从 df_coords_np 中选择对应的行,然后从这些行中选择第1列(即Y坐标)。pd.DataFrame({“X”: extracted_x, “Y”: extracted_y}): 最后,将提取出的X和Y数组构建成一个新的Pandas DataFrame。

优点:

高性能: NumPy的矢量化操作在底层使用C语言实现,效率远高于Python循环。代码简洁: 相比于循环,矢量化代码通常更简洁、更易读(对于熟悉NumPy的用户)。内存效率: 减少了中间数据结构的创建。

4. 性能对比与最佳实践

在处理中小型数据集时,两种方法可能在执行时间上差异不大。然而,当 tours 列表包含成千上万甚至数百万个元素时,NumPy的矢量化方法将展现出压倒性的性能优势。

最佳实践建议:

优先使用矢量化操作: 在Pandas和NumPy中,只要有可能,就应优先考虑使用矢量化操作来代替显式的Python循环。理解数据结构: 在进行复杂索引和数据提取时,清晰地理解原始数据(df)和索引数据(tours)的结构是至关重要的。验证结果: 无论采用哪种方法,都应在小规模数据集上验证输出结果的正确性。

5. 总结与展望

本教程展示了两种从索引映射构建坐标DataFrame的方法。虽然基于循环和字典的方法直观易懂,但利用NumPy进行矢量化处理是更高效、更专业的解决方案,尤其适用于大规模数据处理。

最终生成的 coord DataFrame(无论是通过方法一的改进版还是方法二)都包含了我们需要的X和Y坐标对。这个DataFrame可以直接用于后续的数据可视化任务,例如使用Matplotlib、Seaborn或Plotly等库绘制路径或散点图。例如,要绘制路径,可以直接使用 coord[‘X’] 和 coord[‘Y’] 作为绘图函数的输入。

# 示例:使用matplotlib绘制路径(需要安装matplotlib)# import matplotlib.pyplot as plt# plt.figure(figsize=(10, 8))# plt.plot(coord_vectorized['X'], coord_vectorized['Y'], marker='o', linestyle='-', color='blue')# plt.title('Generated Route Coordinates')# plt.xlabel('X Coordinate')# plt.ylabel('Y Coordinate')# plt.grid(True)# plt.show()

掌握这种高效的数据提取和重构技术,将极大地提升您在Python数据科学项目中的工作效率。

以上就是利用Pandas和NumPy高效从索引映射生成坐标DataFrame的详细内容,更多请关注创想鸟其它相关文章!

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

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月14日 20:44:12
下一篇 2025年12月14日 20:44:26

相关推荐

  • Go语言:理解与使用数组指针作为函数参数

    本文深入探讨了Go语言中如何将数组指针作为函数参数传递,并阐明了数组大小作为类型一部分的关键特性及其对函数签名的影响。我们将通过示例代码展示其用法,并对比分析了数组指针与更常用、更灵活的切片(slice)在参数传递上的异同,旨在帮助开发者理解Go语言中处理集合类型数据的最佳实践。 如何向函数传递数组…

    2025年12月15日
    000
  • Go语言中数组指针的传递与使用:深入理解其特性与局限

    本文深入探讨Go语言中如何传递数组指针,包括其语法、在函数中接收和使用的方法。重点阐述了数组指针的一个核心局限:数组大小是其类型的一部分,导致函数签名必须与特定大小的数组精确匹配。文章对比了数组指针与切片(Slic++e)的适用场景,并强调了在Go语言中,切片通常是更灵活、更推荐的数据传递方式,同时…

    2025年12月15日
    000
  • 在 Go 中整合 C 和 Python 代码实现 Markdown 解析

    本文旨在指导开发者如何在 Go 语言中利用 CGO 和 go-python 整合 C 和 Python 代码,以实现 Markdown 文本到 HTML 的转换。文章将重点介绍使用 CGO 封装 C 语言编写的 Markdown 解析库,并简要提及 go-python 的使用场景,同时推荐使用纯 G…

    2025年12月15日
    000
  • Go语言核心概念解析:深入理解关键特性

    go语言的核心概念包括并发模型、内存管理、类型系统等,旨在平衡性能与开发效率。1.并发模型基于goroutine和channel,goroutine是轻量级线程,通过channel进行类型安全的消息传递,实现高效并行处理;2.内存管理采用垃圾回收机制,自动分配和释放内存,减少泄漏风险,同时优化gc停…

    2025年12月15日 好文分享
    000
  • Golang如何实现错误分类统计 使用prometheus监控错误指标

    要对golang程序中的错误进行分类统计,可结合prometheus实现,具体步骤如下:1. 定义错误类型(如数据库错误、网络请求失败等),并使用prometheus.newcountervec创建指标记录每种错误的发生次数;2. 在应用中启动http服务并注册prometheus.handler(…

    2025年12月15日 好文分享
    000
  • Golang的RPC如何实现跨语言调用 协议兼容性与实践

    要实现 golang 的 rpc 跨语言调用,关键在于替换默认的 gob 编码为通用协议。1. 使用通用协议替代 gob:可选 json-rpc 或 grpc+protobuf,前者适合轻量级交互,后者适合高性能和强类型接口;2. json-rpc 实现要点:需定义导出字段的结构体参数,使用 jso…

    2025年12月15日 好文分享
    000
  • Go语言中持有工厂函数的正确姿势

    本文介绍了如何在 Go 语言中正确地持有工厂函数,并提供了一个完整的示例,展示了如何定义接口、函数类型,以及如何在结构体中存储和使用工厂函数来创建特定接口的实例。通过本文,你将学会如何在 Go 中实现类似 Python 中创建对象工厂的功能。 在 Go 语言中,函数是一等公民,可以像其他类型一样被传…

    2025年12月15日
    000
  • Go语言切片索引:深入理解半开区间[low:high]的逻辑

    Go语言中切片或数组的索引操作 b[low:high] 采用半开区间 [low, high) 的逻辑,表示切片从 low 索引处开始,到 high 索引处结束(不包含 high 索引处的元素)。这种设计与零基索引体系相辅相成,使得索引值指向元素的“起始边界”,从而确保了切片长度的直观计算,并与多数编…

    2025年12月15日
    000
  • 探索Go语言在项目开发中的应用场景与选择考量

    Go语言最初作为一门实验性语言,其早期应用受限于不成熟的生态系统和有限的库支持。然而,经过十余年的发展,Go已成长为一门稳定、高效且拥有强大社区支持的成熟语言,广泛应用于构建高性能网络服务、分布式系统、云计算基础设施及命令行工具等领域。本文将探讨Go语言的演进过程,并深入分析其在现代项目开发中的优势…

    2025年12月15日
    000
  • Go语言:早期阶段的项目适用性分析

    本文探讨了Go语言在其早期实验阶段的项目适用性。鉴于其实现和生态系统尚不成熟,Go语言当时更适合用于实验性项目,因为缺乏丰富的框架和库可能导致开发效率低于使用成熟语言的项目。 Go语言早期阶段的定位与挑战 在go语言刚刚问世并处于实验性阶段时,其作为谷歌推出的一门新型编程语言,引起了业界的广泛关注。…

    2025年12月15日
    000
  • Golang中哪些内置类型本质是指针类型 分析map/channel/function的内部实现

    go语言中map、channel和function是引用类型的原因在于它们底层实现均通过指针进行数据共享。1. map本质是指向runtime.hmap结构的指针,赋值或传递时复制的是该指针,操作直接影响原始数据;2. channel底层是指向runtime.hchan结构的指针,包含缓冲区、互斥锁…

    2025年12月15日 好文分享
    000
  • Go语言切片索引机制解析:理解半开区间与零基索引

    本文深入探讨Go语言中切片(Slice)的索引机制,重点解析其半开区间表示法([low:high])和零基索引的内在逻辑。通过图示和示例,阐明为何b[1:4]会引用元素1、2、3,而非1至4,并指出这种设计在计算机科学中的普遍性,帮助开发者精确掌握Go语言切片操作的精髓。 Go语言切片的基础概念 在…

    2025年12月15日
    000
  • 明确Go语言的适用场景:从实验性探索到生产级应用

    Go语言最初被视为实验性工具,但经过多年的发展,已凭借其并发特性、高效性能和简洁语法,在后端服务、网络编程、云计算和DevOps工具等领域展现出卓越能力,成为构建高性能、可伸缩系统的重要选择。 1. go语言的演进与核心优势 Go语言,由Google在2009年推出,其诞生之初确实带有一定的实验性质…

    2025年12月15日
    000
  • 深入理解 Go 语言切片(Slice)的索引机制与半开区间表示法

    本文深入探讨 Go 语言切片(Slice)的索引机制,特别是其采用的零基索引和“半开区间”表示法 [low:high)。我们将详细解释为何 b[1:4] 会引用数组中索引为 1、2、3 的元素,而不是 1 到 4,并通过可视化方式阐明索引边界的逻辑。文章还将探讨这种机制与其他编程语言的共通性,并提供…

    2025年12月15日
    000
  • Go语言切片索引:深入解析半开区间[low:high]的逻辑

    Go语言中的切片(slice)操作遵循“半开区间”原则,即slice[low:high]包含索引low处的元素,但不包含索引high处的元素。这种设计与零基索引体系高度一致,将索引视为元素之间的“位置”,而非元素本身,从而使切片长度的计算(high – low)直观且避免了“差一错误”,…

    2025年12月15日
    000
  • 评估Go语言早期阶段的项目适用性

    本文探讨了Go语言在其早期实验阶段的项目适用性。鉴于Go当时仍处于起步阶段,其实现和生态系统均不成熟,缺乏丰富的框架和库支持。因此,在这一时期,Go语言主要适用于实验性项目,开发者需准备好投入更多精力进行基础编码,开发效率可能低于使用成熟语言。 Go语言早期阶段的特性 在go语言问世之初,它被定位为…

    2025年12月15日
    000
  • Go 语言切片索引机制详解:为什么 b[1:4] 包含元素 1,2,3

    本文深入解析 Go 语言中切片(slice)的索引机制,特别是 b[low:high] 表达式采用半开区间 [low, high) 的设计哲学。我们将探讨为何 b[1:4] 引用的是索引为 1、2、3 的元素,而非 1 至 4,并解释这与零基索引语言的普遍一致性,通过图示和代码示例帮助读者透彻理解 …

    2025年12月15日
    000
  • GolangWeb应用如何监控性能指标 集成Prometheus采集暴露端点

    给golang web应用集成prometheus监控的核心方法是:让应用自身暴露指标,再由prometheus抓取。具体步骤如下:1. 引入prometheus go客户端库并定义指标,如counter、gauge、histogram等;2. 在代码中埋点,记录http请求数、延迟、gorouti…

    2025年12月15日 好文分享
    000
  • Golang值类型在函数调用时的隐式拷贝 通过案例展示内存变化

    go语言函数调用默认按值传递,会复制参数变量,对值类型如struct修改不影响原变量。1. 传值本质是复制一份操作,modify函数修改的是副本;2. 大结构体频繁传值会引发性能瓶颈,建议用指针传递;3. 即使小结构体如point也有拷贝成本,高频调用时需注意优化;4. 可通过汇编查看拷贝过程,帮助…

    2025年12月15日 好文分享
    000
  • Golang的错误处理机制是什么 Golang error处理最佳实践

    golang的错误处理机制通过显式返回error值实现。函数需返回error类型,调用者检查该值是否为nil以判断操作成败。使用error接口是核心方案,例如func divide返回(int, error)。其次,采用错误包装(如fmt.errorf搭配%w)保留原始上下文。第三,定义自定义错误类…

    2025年12月15日 好文分享
    000

发表回复

登录后才能评论
关注微信