社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python Pandas数据处理,10个高频使用技巧

python • 2 周前 • 131 次点击  

Pandas是Python中最强大的数据分析工具之一,在数据科学、金融分析、机器学习等领域被广泛应用。熟练掌握Pandas可以显著提高数据处理效率。本文将介绍10个Pandas高频使用技巧,这些技巧在实际工作中非常实用,可以帮助更高效地处理数据。

一、高效读取大型CSV文件

处理大型数据集时,内存消耗是一个常见问题。Pandas提供了分块读取的方法,可以有效降低内存压力:

import pandas as pd
import numpy as np

# 常规读取方式
# df = pd.read_csv('large_file.csv')  # 可能导致内存溢出

# 高效读取方式:分块读取
chunk_size = 10000
data_chunks = []

for chunk in pd.read_csv('large_file.csv', chunksize=chunk_size):
    # 对每个数据块进行处理
    processed_chunk = chunk.query('value > 0')  # 示例:筛选正值
    data_chunks.append(processed_chunk)
    
# 合并处理后的数据块
result_df = pd.concat(data_chunks, ignore_index=True)

# 或者直接迭代处理而不保存所有数据
total_sum = 0
for chunk in pd.read_csv('large_file.csv', chunksize=chunk_size):
    total_sum += chunk['value'].sum()

print(f"数据总和: {total_sum}")

这种方法可以处理远大于内存容量的文件,非常适合大数据场景。

二、使用查询字符串进行数据筛选

Pandas的query方法提供了一种简洁的方式来筛选数据,比传统的布尔索引更加直观:

import pandas as pd

# 创建示例数据框
df = pd.DataFrame({
    'A': np.random.rand(100000),
    'B': np.random.rand(100000),
    'C': np.random.choice(['X''Y''Z'], 100000)
})

# 传统方式
filtered_df1 = df[(df['A'] > 0.5) & (df['B'] 0.5) & (df['C'] == 'X')]

# 使用query(通常更快且更可读)
filtered_df2 = df.query('A > 0.5 and B < 0.5 and C == "X"')

# 使用变量
threshold_a = 0.5
threshold_b = 0.5
filtered_df3 = df.query('A > @threshold_a and B < @threshold_b')

query方法不仅使代码更加简洁,在处理大型数据集时通常也会有更好的性能。

三、多级索引的高效操作

在处理复杂数据时,多级索引(MultiIndex)是一个强大的功能:

import pandas as pd

# 创建多级索引的DataFrame
arrays = [
    ['北京''上海''广州''北京''上海''广州'],
    ['2021''2021''2021''2022''2022''2022']
]
index = pd.MultiIndex.from_arrays(arrays, names=('城市''年份'))
df = pd.DataFrame({
    '销售额': [1001209011013595],
    '成本': [708065758568]
}, index=index)

# 基于索引级别访问数据
beijing_data = df.loc['北京']
year_2021_data = df.xs('2021', level='年份')

# 按索引级别分组计算
city_avg = df.groupby(level='城市').mean()
growth = df.groupby(level='城市').pct_change()

# 在多级索引间转换
pivoted = df.unstack(level='年份')  # 将年份从索引变为列
stacked = pivoted.stack()  # 将列转回索引

多级索引可以更优雅地组织复杂的数据结构,减少数据冗余。

四、列数据类型转换与内存优化

优化DataFrame的内存使用是处理大数据的重要技巧:

import pandas as pd
import numpy as np

# 创建示例数据
df = pd.DataFrame({
    'id': range(1000000),
    'value': np.random.rand(1000000),
    'category': np.random.choice(['A''B''C''D'], 1000000)
})

# 查看初始内存使用
print(f"初始内存使用: {df.memory_usage().sum() / 1024**2:.2f} MB")

# 优化整数列
df['id'] = pd.to_numeric(df['id'], downcast='integer')

# 优化浮点列
df['value'] = pd.to_numeric(df['value'], downcast='float')

# 将分类数据转换为category类型
df['category'] = df['category'].astype('category')

# 查看优化后内存使用
print(f"优化后内存使用: {df.memory_usage().sum() / 1024**2:.2f} MB")

通过合理设置数据类型,可以显著减少DataFrame的内存占用,有时能节省70%以上的内存。

五、使用apply和map进行高效数据转换

Pandas提供了多种方法来转换数据,选择合适的方法能够显著提升性能:

import pandas as pd
import numpy as np

# 创建示例数据
df = pd.DataFrame({
    'A': range(1000000),
    'B': range(1000000)
})

# 不同的数据转换方法

# 1. 使用向量化操作(最快)
df['C'] = df['A'] + df['B']

# 2. 使用apply(对于无法向量化的复杂操作)
def complex_operation(row):
    # 模拟复杂计算
    return np.sqrt(row['A'] ** 2 + row['B'] ** 2)

df['D'] = df.apply(complex_operation, axis=1)

# 3. 使用map(适用于Series上的元素级转换)
mapping = {i: i**2for i in range(10)}  # 小型映射字典
df['E'] = df['A'].map(lambda x: x % 10).map(mapping)

# 4. 使用列表推导式(有时比apply更快)
df['F'] = [a * b for a, b in zip(df['A'], df['B'])]

# 5. 使用NumPy方法(通常最高效)
df['G'] = np.sqrt(np.square(df['A']) + np.square(df['B']))

在实际应用中,应尽量使用向量化操作或NumPy函数,它们通常比apply和map快10-100倍。

六、时间序列数据处理

Pandas的时间序列功能非常强大,适合处理金融、传感器等时间相关数据:

import pandas as pd
import numpy as np

# 创建日期范围
date_range = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
df = pd.DataFrame({
    'date': date_range,
    'value': np.random.randn(len(date_range)).cumsum()
})
df.set_index('date', inplace=True)

# 重采样 - 降低频率(如日数据转为月数据)
monthly_avg = df.resample('M').mean()
weekly_max = df.resample('W').max()

# 重采样 - 提高频率(如填充缺失的小时数据)
hourly_data = df.resample('H').ffill()  # 前向填充

# 移动窗口计算
df['7D_rolling_avg'] = df['value'].rolling(window='7D').mean()
df['30D_rolling_std'] = df['value'].rolling(window='30D').std()

# 时间偏移
df['prev_month'] = df['value'].shift(30)  # 前30天的值
df['yoy_change'] = df['value'] - df['value'].shift(365)  # 同比变化

# 按季度、月份等分组
quarterly_data = df.groupby(pd.Grouper(freq='Q')).agg(['mean''min''max'])
month_of_year = df.groupby(df.index.month).mean()  # 各月平均值

这些方法可以轻松处理复杂的时间序列分析任务,如趋势分析、季节性分析等。

七、高效合并和连接多个DataFrame

数据合并是日常数据处理的常见操作,Pandas提供了多种方法:

import pandas as pd

# 创建示例数据
df1 = pd.DataFrame({
    'key': ['A''B''C''D'],
    'value1': [1234]
})

df2 = pd.DataFrame({
    'key': ['B''D''E''F'],
    'value2': [5678]
})

# 1. 使用merge进行SQL风格连接
inner_join = pd.merge(df1, df2, on='key')  # 内连接
left_join = pd.merge(df1, df2, on='key', how='left')  # 左连接
outer_join = pd.merge(df1, df2, on='key', how='outer')  # 外连接

# 2. 使用concat垂直或水平组合数据
vertical_concat = pd.concat([df1, df2], ignore_index=True)  # 垂直合并
horizontal_concat = pd.concat([df1, df2], axis=1)  # 水平合并

# 3. 使用join基于索引合并
df1.set_index('key', inplace=True)
df2.set_index('key', inplace=True)
joined = df1.join(df2, how='inner')  # 基于索引的内连接

# 4. 高性能合并大型数据集
# 对大型数据集,先排序再合并可以提高性能
df1_sorted = df1.sort_index()
df2_sorted = df2.sort_index()
efficient_join = pd.merge_asof(df1_sorted, df2_sorted, left_index=True, right_index=True)

选择合适的合并方法取决于具体需求和数据结构,合理使用可以避免不必要的数据复制和内存消耗。

八、使用分组操作进行高效数据分析

分组运算是数据分析的核心功能之一,能够揭示数据中的模式和趋势:

import pandas as pd
import numpy as np

# 创建示例销售数据
np.random.seed(42)
df = pd.DataFrame({
    '产品': np.random.choice(['A''B''C''D'], 1000),
    '区域': np.random.choice(['东部''西部''南部''北部'], 1000),
    '销售员': np.random.choice(['张三''李四''王五''赵六''钱七'], 1000),
    '销售额': np.random.randint(100100001000),
    '日期': pd.date_range('2023-01-01', periods=1000)
})

# 1. 基本分组统计
region_stats = df.groupby('区域')['销售额'].agg(['sum''mean''count'])

# 2. 多级分组
product_region_stats = df.groupby(['产品''区域'])['销售额'].sum().unstack()

# 3. 按时间分组
monthly_sales = df.groupby(pd.Grouper(key='日期', freq='M'))['销售额'].sum()

# 4. 使用自定义聚合函数
def range_stat(x):
    return x.max() - x.min()

custom_agg = df.groupby('销售员')['销售额'].agg([
    ('总额''sum'),
    ('平均值''mean'),
    ('最大值''max'),
    ('最小值''min'),
    ('范围', range_stat)
])

# 5. 分组转换和过滤
# 标准化每个组内的销售额
df['标准化销售额'] = df.groupby('产品')['销售额'].transform(
    lambda x: (x - x.mean()) / x.std()
)

# 筛选销售额高于组平均值的记录
group_means = df.groupby('区域')['销售额'].transform('mean')
high_performers = df[df['销售额'] > group_means]

分组操作可以深入挖掘数据中的关系和模式,是数据分析的强大工具。

九、处理缺失值

实际数据集常常包含缺失值,正确处理它们对于数据分析至关重要:

import pandas as pd
import numpy as np

# 创建带有缺失值的数据
df = pd.DataFrame({
    'A': [12, np.nan, 45],
    'B': [np.nan, 23, np.nan, 5],
    'C': [1234, np.nan],
    'D': [np.nan, np.nan, np.nan, np.nan, np.nan],
    'E': [12345]
})

# 1. 检查缺失值
missing_count = df.isnull().sum()
missing_percent = (df.isnull().sum() / len(df)) * 100

# 2. 基于条件填充缺失值
df['A'] = df['A'].fillna(df['A'].mean())  # 使用平均值填充A列
df['B'] = df['B'].fillna(method= 'ffill')  # 使用前向填充法
df['C'] = df['C'].fillna(method='bfill')  # 使用后向填充法

# 3. 使用插值法填充缺失值
df['D'] = df['D'].interpolate(method='linear')  # 线性插值
df['D'] = df['D'].interpolate(method='polynomial', order=2)  # 多项式插值

# 4. 基于多列填充缺失值
# 使用其他列构建预测模型填充缺失值
from sklearn.impute import KNNImputer
imputer = KNNImputer(n_neighbors=2)
df_filled = pd.DataFrame(
    imputer.fit_transform(df),
    columns=df.columns
)

# 5. 按组填充缺失值
# 例如,按产品类别的平均价格填充缺失的价格
product_df = pd.DataFrame({
    '产品': ['A''A''B''B''C'],
    '类别': ['电子''电子''服装''服装''电子'],
    '价格': [100, np.nan, 50, np.nan, 75]
})

product_df['价格'] = product_df.groupby('类别')['价格'].transform(
    lambda x: x.fillna(x.mean())
)

选择合适的缺失值处理方法应基于数据的性质和分析目标,而不是机械地删除或填充。

十、高级索引和查询

在处理大型数据集时,高效的索引和查询方法可以显著提升性能:

import pandas as pd


    

import numpy as np

# 创建大型数据集
df = pd.DataFrame({
    'id': range(1000000),
    'category': np.random.choice(['A''B''C''D''E'], 1000000),
    'value1': np.random.rand(1000000),
    'value2': np.random.rand(1000000),
    'date': pd.date_range('2020-01-01', periods=1000000, freq='T')
})

# 1. 设置正确的索引加速查询
df.set_index('id', inplace=True)  # 设置主键索引
# 查询单个记录
result1 = df.loc[500000]  # 通过索引直接访问(高效)

# 2. 使用布尔索引的高效方法
# 较低效的方法(生成完整的布尔数组)
result2 = df[df['value1'] > 0.5]

# 更高效的方法(使用query和索引)
result3 = df.query('value1 > 0.5')

# 3. 使用分类类型加速
df['category'] = df['category'].astype('category')  # 转换为分类类型
result4 = df[df['category'] == 'A']  # 现在更快

# 4. 时间序列数据的高效索引
df.set_index('date', inplace=True)
# 使用部分索引查询
result5 = df['2020-06']  # 获取2020年6月的所有数据
result6 = df.loc['2020-03-01':'2020-03-31']  # 日期范围查询

# 5. 使用.at和.iat进行单元格访问
# 较慢的方法
value1 = df.loc['2020-01-01 00:30:00''value1']
# 更快的方法
value2 = df.at['2020-01-01 00:30:00''value1']

# 使用整数位置更快地访问
first_cell = df.iat[00]  # 访问第一行第一列

在处理大型数据集时,正确的索引和查询方法可以将查询速度提高数倍至数十倍。

总结

Pandas是数据分析过程中不可或缺的工具,掌握这10个高频使用技巧可以显著提升数据处理效率。从高效读取大型文件,到复杂的数据转换、分组计算、时间序列分析,再到性能优化,这些技巧覆盖了日常数据分析工作中最常见的场景。随着数据规模的不断增长,高效处理大型数据集的能力变得越来越重要。希望这些技巧能帮助你更好地利用Pandas的强大功能,提高数据分析和处理效率。

如果你觉得文章还不错,请大家 点赞、分享、留言 下,因为这将是我持续输出更多优质文章的最强动力!


我们还为大家准备了Python资料,感兴趣的小伙伴快来找我领取一起交流学习哦!

图片

往期推荐

历时一个月整理的 Python 爬虫学习手册全集PDF(免费开放下载)

Beautiful Soup快速上手指南,从入门到精通(PDF下载)

Python基础学习常见的100个问题.pdf(附答案)

124个Python案例,完整源代码!

30 个Python爬虫的实战项目(附源码)

从入门到入魔,100个Python实战项目练习(附答案)!

80个Python数据分析必备实战案例.pdf(附代码),完全开放下载

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/181280
 
131 次点击