【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.10 文本数据炼金术:从CSV到结构化数组

在这里插入图片描述

1.10 《文本数据炼金术:从CSV到结构化数组》

目录
Syntax error in textmermaid version 10.9.0

1.10.1 引言

在数据科学和机器学习领域,处理文本数据是一项常见的任务。CSV(Comma-Separated Values)文件是一种常用的文本数据格式,它们以逗号分隔的值来存储数据。将CSV文件转换为NumPy的结构化数组可以显著提高数据处理的效率和灵活性。本文将详细探讨如何从CSV文件中读取数据并将其转换为NumPy的结构化数组,同时介绍处理缺失值、大文件分块读取优化、时区转换等高级处理技巧,并与Pandas进行互操作对比。

Syntax error in textmermaid version 10.9.0

1.10.2 结构化数据类型定义详解

1.10.2.1 什么是结构化数组?

结构化数组(Structured Array)是NumPy中的一种高级数据类型,它允许每个字段有不同的数据类型。与普通的NumPy数组相比,结构化数组具有更强的描述性和灵活性,适用于处理复杂的数据结构。

1.10.2.2 创建结构化数组

可以使用numpy.dtype对象来定义结构化数据类型。以下是一个简单的例子:

import numpy as np

# 定义结构化数据类型
dtype = np.dtype([
    ('name', 'U20'),  # 姓名,使用Unicode字符串,最多20个字符
    ('age', 'i4'),    # 年龄,使用32位整数
    ('gender', 'U10'), # 性别,使用Unicode字符串,最多10个字符
    ('height', 'f8')  # 身高,使用64位浮点数
])

# 创建结构化数组
data = np.array([
    ('Alice', 25, 'Female', 165.5),
    ('Bob', 30, 'Male', 175.0),
    ('Charlie', 35, 'Male', 180.0)
], dtype=dtype)

print(data)

1.10.2.3 数据类型映射表(Python↔NumPy)

Python Data TypeNumPy Data Type
int‘i4’
float‘f8’
str‘U20’ or ‘S20’
bool‘b1’
datetime‘datetime64’
None‘O’ (object)

1.10.2.4 结构化数组的操作

结构化数组支持各种NumPy的操作,如索引、切片、排序等。以下是一些示例:

# 索引
print(data['name'])  # 输出所有姓名

# 切片
print(data[1:3])  # 输出第2和第3个记录

# 排序
sorted_data = np.sort(data, order='age')  # 按年龄排序
print(sorted_data)

1.10.2.5 多字段排序

多字段排序允许我们根据多个字段对结构化数组进行排序。例如,我们可以先按年龄排序,再按身高排序:

sorted_data = np.sort(data, order=['age', 'height'])
print(sorted_data)

1.10.2.6 内存效率

结构化数组在内存使用上比普通数组更高效,因为它可以精确地存储每个字段的数据类型和大小。这对于处理大规模数据集非常有帮助。

1.10.3 处理缺失值的5种策略

1.10.3.1 填充默认值

对于缺失值,最简单的处理方式是填充默认值。例如,对于整数字段,可以填充0;对于浮点数字段,可以填充np.nan

data = np.array([
    ('Alice', 25, 'Female', 165.5),
    ('Bob', 30, 'Male', np.nan),  # 缺失值
    ('Charlie', 35, 'Male', 180.0)
], dtype=dtype)

# 填充默认值
data['height'] = np.nan_to_num(data['height'], nan=0.0)  # 将nan填充为0.0
print(data)

1.10.3.2 插值

插值是一种常用的数据填充方法。NumPy提供了多种插值方法,如线性插值和最近邻插值。

import pandas as pd

df = pd.DataFrame(data)
df['height'] = df['height'].interpolate()  # 线性插值
data = df.to_records(index=False)  # 转换回NumPy结构化数组
print(data)

1.10.3.3 删除缺失值的记录

如果缺失值不影响整体数据,可以考虑删除这些记录。

data = data[~np.isnan(data['height'])]  # 删除height字段为nan的记录
print(data)

1.10.3.4 使用掩码数组

NumPy的掩码数组(Masked Array)可以方便地处理缺失值。

masked_data = np.ma.masked_invalid(data['height'])  # 创建掩码数组
print(masked_data)

1.10.3.5 使用特殊标记

在某些情况下,可以使用特殊标记来表示缺失值,例如-1或-999。

data['height'] = np.where(np.isnan(data['height']), -999, data['height'])  # 将nan填充为-999
print(data)

1.10.4 大文件分块读取优化

1.10.4.1 问题背景

处理大规模的CSV文件时,一次性加载所有数据到内存中可能会导致内存溢出。因此,需要使用分块读取的方法来优化性能。

1.10.4.2 使用numpy.loadtxt分块读取

numpy.loadtxt可以通过设置skiprowsmax_rows参数来实现分块读取。

import numpy as np

def read_chunk(file, dtype, skiprows, max_rows):
    return np.loadtxt(file, dtype=dtype, delimiter=',', skiprows=skiprows, max_rows=max_rows)

# 定义结构化数据类型
dtype = np.dtype([
    ('name', 'U20'),
    ('age', 'i4'),
    ('gender', 'U10'),
    ('height', 'f8')
])

# 读取大文件
chunk_size = 1000
with open('large_file.csv', 'r') as file:
    for i in range(0, 10000, chunk_size):
        chunk = read_chunk(file, dtype, i, chunk_size)
        print(f"读取了第{i + 1}到第{i + chunk_size}行数据")
        print(chunk)

1.10.4.3 使用生成器实现流式处理

生成器是一种更高效的方法,可以在读取数据时进行处理,而无需将所有数据加载到内存中。

def read_csv_in_chunks(file, dtype, chunk_size=1000):
    with open(file, 'r') as f:
        while True:
            chunk = np.loadtxt(f, dtype=dtype, delimiter=',', max_rows=chunk_size)
            if len(chunk) == 0:
                break
            yield chunk

# 读取大文件
dtype = np.dtype([
    ('name', 'U20'),
    ('age', 'i4'),
    ('gender', 'U10'),
    ('height', 'f8')
])

for i, chunk in enumerate(read_csv_in_chunks('large_file.csv', dtype)):
    print(f"读取了第{i * chunk_size + 1}到第{(i + 1) * chunk_size}行数据")
    print(chunk)

1.10.4.4 Dask库的使用

Dask是一个用于并行计算的库,可以轻松处理大规模的数据集。

import dask.array as da

# 读取大文件
dask_data = da.from_csv('large_file.csv', dtype=dtype, blocksize=1000 * 1024)  # 每块1MB
print(dask_data)

1.10.5 时区转换等高级处理

1.10.5.1 时区转换的重要性

在处理时间数据时,时区转换是一个关键步骤。不同的时区会导致时间戳的不一致,影响数据分析的准确性。

1.10.5.2 时区转换的实现

NumPy的时间戳类型datetime64支持时区转换。以下是一个简单的示例:

import numpy as np
import pytz
from datetime import datetime

# 生成带时区的日期时间
dt = np.datetime64('2023-01-01T00:00:00', 'ns').astype(datetime).replace(tzinfo=pytz.utc)
print(dt)

# 转换时区
dt = dt.astimezone(pytz.timezone('Asia/Shanghai'))
print(dt)

1.10.5.3 带时区的时间戳转换实战

实际应用中,我们可能需要处理包含时间戳的CSV文件,并进行时区转换。

import numpy as np
import pytz
from datetime import datetime

# 定义结构化数据类型
dtype = np.dtype([
    ('name', 'U20'),
    ('age', 'i4'),
    ('gender', 'U10'),
    ('timestamp', 'datetime64[ns]')  # 时间戳字段
])

# 读取数据
data = np.loadtxt('large_file.csv', dtype=dtype, delimiter=',')

# 转换时区
def convert_timezone(timestamp, from_tz, to_tz):
    dt = timestamp.astype(datetime).replace(tzinfo=from_tz)
    return dt.astimezone(to_tz).timestamp()

from_tz = pytz.utc
to_tz = pytz.timezone('Asia/Shanghai')

data['timestamp'] = np.vectorize(convert_timezone)(data['timestamp'], from_tz, to_tz)
print(data)

1.10.5.4 时区转换的性能优化

时区转换是一个计算密集型操作,可以使用NumPy的矢量化函数来提高性能。

# 矢量化时区转换函数
convert_timezone_vec = np.vectorize(convert_timezone, otypes=[np.float64])

data['timestamp'] = convert_timezone_vec(data['timestamp'], from_tz, to_tz)
print(data)

1.10.6 结构化数组与Pandas的互操作对比

1.10.6.1 Pandas的优势

Pandas是Python中处理数据的最常用库之一,它提供了丰富的数据处理功能和高效率的性能。

1.10.6.2 从Pandas DataFrames到NumPy结构化数组

Pandas DataFrames可以轻松地转换为NumPy的结构化数组。

import pandas as pd
import numpy as np

# 读取CSV文件
df = pd.read_csv('large_file.csv')

# 转换为NumPy结构化数组
dtype = np.dtype([
    ('name', 'U20'),
    ('age', 'i4'),
    ('gender', 'U10'),
    ('height', 'f8')
])

data = df.to_records(index=False, convert_datetime64=True, dtype=dtype)
print(data)

1.10.6.3 从NumPy结构化数组到Pandas DataFrames

同样,NumPy的结构化数组也可以轻松地转换为Pandas DataFrames。

# 转换为Pandas DataFrames
df = pd.DataFrame(data)
print(df)

1.10.6.4 性能对比

在处理大规模数据时,NumPy通常比Pandas更高效。以下是一个简单的性能对比示例:

import time

# 生成大规模数据
large_data = np.array([
    (f'User{i}', np.random.randint(18, 80), np.random.choice(['Male', 'Female']), np.random.rand())
    for i in range(1000000)
], dtype=dtype)

# 使用NumPy处理
start_time = time.time()
numPy_data = np.sort(large_data, order='age')
end_time = time.time()
print(f"NumPy处理时间: {end_time - start_time:.2f}秒")

# 使用Pandas处理
df = pd.DataFrame(large_data)
start_time = time.time()
pandas_data = df.sort_values(by='age')
end_time = time.time()
print(f"Pandas处理时间: {end_time - start_time:.2f}秒")

1.10.7 总结

本文详细介绍了如何从CSV文件中读取数据并将其转换为NumPy的结构化数组。我们讨论了结构化数据类型的定义、缺失值的处理、大文件的分块读取优化、时区转换等高级处理技巧,并与Pandas进行了互操作对比。

参考文献

参考资料名称链接
NumPy官方文档https://numpy.org/doc/stable/
Pandas官方文档https://pandas.pydata.org/docs/
Dask官方文档https://docs.dask.org/en/latest/
Python官方文档https://docs.python.org/3/
《NumPy用户指南》https://numpy.org/doc/stable/user/index.html
《Pandas用户指南》https://pandas.pydata.org/pandas-docs/stable/user_guide/index.html
《Dask用户指南》https://docs.dask.org/en/latest/user.html
《Python数据科学手册》https://jakevdp.github.io/PythonDataScienceHandbook/
《NumPy教程》https://towardsdatascience.com/numpy-tutorial-e0ebc6d53b6f
《Pandas教程》https://towardsdatascience.com/pandas-tutorial-906df96a3e50
《Dask教程》https://towardsdatascience.com/dask-tutorial-20e2ff974da1
《NumPy性能优化》https://realpython.com/faster-numpy-arrays-cython/
《Pandas性能优化》https://towardsdatascience.com/10-tips-for-faster-pandas-1e52b1d465bb
《Dask性能优化》https://medium.com/condition-red/dask-performance-tips-6d6ce01646c2
《NumPy结构化数组详解》https://numpy.org/doc/stable/user/basics.rec.html
《Pandas处理缺失值》https://pandas.pydata.org/pandas-docs/stable/user_guide/missing_data.html
《Dask读取大文件》https://docs.dask.org/en/latest/array-creation.html
《NumPy时区转换》https://numpy.org/doc/stable/reference/arrays.datetime.html
《Pandas时区转换》https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html
《Dask流式处理》https://docs.dask.org/en/latest/delayed.html
《Python生成器详解》https://realpython.com/introduction-to-python-generators/
《NumPy和Pandas互操作》https://numpy.org/doc/stable/user/basics.interface.html
《NumPy和Pandas性能对比》https://towardsdatascience.com/performance-comparison-of-numpy-vs-pandas-vs-python-list-2c96d35c8b00
《NumPy和Pandas在数据科学中的应用》https://medium.com/@a/data-science-with-numpy-and-pandas-8d2b4c0a4e58
《NumPy和Pandas的最佳实践》https://towardsdatascience.com/numpy-and-pandas-best-practices-b0e0dee09e73
《NumPy和Pandas处理大文件的技巧》https://towardsdatascience.com/working-with-large-data-in-python-and-pandas-9c0ea4d44feb

这篇文章包含了详细的原理介绍、代码示例、源码注释以及案例等。希望这对您有帮助。如果有任何问题请随私信或评论告诉我。
posted @   爱上编程技术  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示