返回

Pandas 数据匹配太慢?试试这两种高效解决方案!

python

如何高效匹配数千条数据:告别Pandas性能瓶颈

你是否也遇到过使用Pandas处理大量数据时,匹配过程缓慢如蜗牛,仿佛时间静止的绝望?本文将深入探讨这一常见问题,并提供行之有效的解决方案,助你摆脱性能瓶颈,让数据处理飞速运转!

Pandas为何如此缓慢?

Pandas作为数据分析利器,在处理小型数据集时表现出色。然而,当面对数千甚至数百万条数据时,其基于行的迭代处理方式便显得力不从心。每次循环都需要遍历整个数据集,如果你的代码中还包含I/O操作或复杂计算,更会雪上加霜,导致效率低下,时间消耗巨大。

以你的问题为例,每次循环都需要打开一个大型txt文件,读取内容并转换为DataFrame,然后进行匹配。这种重复的IO操作和数据转换是造成性能瓶颈的罪魁祸首。

解决方案:优化数据结构,化繁为简

想要提升匹配效率,关键在于优化数据结构,避免重复操作。以下两种方案可以有效解决你的问题:

方案一:字典映射,一步到位

字典是Python中查询效率最高的数据结构之一。将所有邮编和地区代码信息预先加载到字典中,以邮编作为键,地区代码作为值。匹配时,只需根据邮编在字典中查找对应地区代码,实现快速定位,避免了每次循环都进行重复的查找操作。

import pandas as pd

# 模拟从Geonames文件加载数据
data = {
    "28033": "ES-MD",
    "1600-812": "PT-08",
    # ... 其他邮编和地区代码
}

# 创建邮编-地区代码字典
postal_code_mapping = {str(k).zfill(5): v for k, v in data.items()}

# 使用字典快速匹配
def get_region_code(postal_code):
    return postal_code_mapping.get(postal_code.strip(), None)

# 读取报告数据
df = pd.DataFrame({
    "Order Number": [930276, 929670],
    "Date": ["27/09/2022", "27/09/2022"],
    "City": ["Madrid", "Lisboa"],
    "Postal code": ["cp: 28033", "cp: 1600-812"]
})

# 清理邮编数据
df["Postal code"] = df["Postal code"].str.replace(r"[^0-9^-]", "", regex=True).str.strip()

# 应用get_region_code函数,添加地区代码列
df["Region code"] = df["Postal code"].apply(get_region_code)

print(df)

方案二:数据库查询,高效精准

数据库天生就擅长处理大量数据,并针对查询性能进行了极致优化。将Geonames数据导入数据库,例如SQLite或PostgreSQL。利用数据库的索引和查询优化功能,可以快速定位匹配的地区代码。

import sqlite3
import pandas as pd

# 连接数据库 (假设已创建数据库和表)
conn = sqlite3.connect('geonames.db')

# 读取报告数据
df = pd.DataFrame({
    "Order Number": [930276, 929670],
    "Date": ["27/09/2022", "27/09/2022"],
    "City": ["Madrid", "Lisboa"],
    "Postal code": ["cp: 28033", "cp: 1600-812"]
})

# 清理邮编数据
df["Postal code"] = df["Postal code"].str.replace(r"[^0-9^-]", "", regex=True).str.strip()

# 定义查询函数
def get_region_code(postal_code):
    cursor = conn.cursor()
    cursor.execute("SELECT admin_code1 FROM geonames WHERE postal_code = ?", (postal_code,))
    result = cursor.fetchone()
    return result[0] if result else None

# 应用get_region_code函数,添加地区代码列
df["Region code"] = df["Postal code"].apply(get_region_code)

print(df)

# 关闭数据库连接
conn.close()

常见问题解答

  1. 两种方案哪个更适合我?

    如果你的数据量较小,并且对实时性要求不高,字典映射方案更简单易用。如果你的数据量很大,并且需要频繁进行匹配操作,数据库查询方案性能更佳。

  2. 如何选择合适的数据库?

    SQLite 轻量级,适合单机使用;PostgreSQL 功能强大,适合大型项目或需要并发访问的场景。

  3. 如何优化数据库查询速度?

    创建索引是提升数据库查询速度的关键。

  4. 除了以上两种方案,还有其他方法吗?

    你可以使用专门用于数据匹配的库,例如recordlinkage,它提供了更丰富的功能,但也需要更高的学习成本。

  5. 如何获取Geonames数据?

    你可以从Geonames官网下载数据,也可以使用OpenDataSoft等平台提供的API接口获取数据。