登录
首页 >  文章 >  python教程

PythonPandas数据处理入门指南

时间:2025-08-31 23:32:50 277浏览 收藏

想入门Python数据分析?这篇Pandas教程为你量身定制!Pandas作为Python数据科学的基石,提供了高效的数据结构和分析工具,如同数据分析领域的瑞士军刀。本教程将带你快速掌握Pandas的核心用法,从安装导入开始,深入讲解DataFrame和Series的创建、数据读取与初步探索(如head(), tail(), info(), describe()等)。你将学会如何进行数据选择与过滤(loc和iloc的使用),以及关键的数据清洗技巧,包括缺失值处理(dropna(), fillna())、重复值处理(drop_duplicates())、异常值检测与处理(IQR),文本数据清洗(str方法)和日期时间数据处理(to_datetime())。此外,还将介绍数据聚合与分组分析(groupby()),以及数据合并与连接(pd.merge(), pd.concat())。本文还总结了实际项目中的常见陷阱和最佳实践,助你避免链式赋值警告、性能问题和内存占用等问题,让你的数据分析之路更加顺畅。

Pandas数据清洗常用技巧包括处理缺失值、重复值、异常值、文本数据、日期时间及数据标准化。具体为:用dropna()或fillna()处理缺失值;drop_duplicates()去除重复数据;通过IQR或标准差识别异常值并合理处理;利用str方法清洗文本,如去空格、大小写转换;用to_datetime统一日期格式;结合业务需求进行数据归一化。同时需注意链式赋值警告、性能优化和内存管理等最佳实践。

Python怎么使用Pandas库_Pandas数据处理入门指南

Pandas是Python数据科学领域的一把瑞士军刀,它提供了一系列高效的数据结构和数据分析工具,让你能轻松处理和分析表格型数据,就像在用一个超级强大的Excel。无论是数据清洗、转换、聚合还是探索性分析,Pandas都能提供直观且高性能的解决方案。

解决方案

要开始使用Pandas,第一步通常是导入它,约定俗成地使用pd作为别名。

import pandas as pd
import numpy as np # 经常和Pandas一起使用

1. 创建数据结构:DataFrame和Series

Pandas最核心的两个数据结构是DataFrame和Series。Series可以看作带标签的一维数组,而DataFrame则是一个二维的、表格型数据结构,每列可以有不同的数据类型。

创建Series:

s = pd.Series([1, 3, 5, np.nan, 6, 8])
print(s)
# 输出:
# 0    1.0
# 1    3.0
# 2    5.0
# 3    NaN
# 4    6.0
# 5    8.0
# dtype: float64

创建DataFrame,这通常是我们日常工作中打交道最多的。可以从字典、列表的列表,或者直接从CSV、Excel文件加载。

# 从字典创建DataFrame
data = {
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [25, 30, 28, 35],
    '城市': ['北京', '上海', '广州', '深圳'],
    '薪资': [8000, 12000, 9000, 15000]
}
df = pd.DataFrame(data)
print(df)
# 输出:
#   姓名  年龄  城市    薪资
# 0  张三  25  北京   8000
# 1  李四  30  上海  12000
# 2  王五  28  广州   9000
# 3  赵六  35  深圳  15000

2. 从文件加载数据

真实世界的数据很少是手动输入的,更多是从文件读取。Pandas对多种文件格式提供了强大的支持。

# 读取CSV文件
# df_csv = pd.read_csv('your_data.csv')

# 读取Excel文件
# df_excel = pd.read_excel('your_data.xlsx', sheet_name='Sheet1')

# 读取JSON文件
# df_json = pd.read_json('your_data.json')

通常,pd.read_csv() 是最常用的函数,因为它能处理各种分隔符、编码问题。

3. 数据查看与初步探索

拿到数据后,第一件事是看看它长什么样。

print(df.head()) # 查看前5行
print(df.tail(3)) # 查看后3行
print(df.info()) # 查看数据概览,包括列名、非空值数量、数据类型
print(df.describe()) # 对数值列进行统计描述,如均值、标准差、最大最小值等
print(df.shape) # 查看行数和列数 (rows, columns)
print(df.columns) # 查看所有列名

4. 数据选择与过滤

这是数据分析的基础操作,如何精准地取出你想要的数据。

选择单列或多列:

print(df['姓名']) # 选择单列,返回Series
print(df[['姓名', '薪资']]) # 选择多列,返回DataFrame

使用lociloc进行行和列的选择:

  • loc:基于标签(列名、行索引)选择。
  • iloc:基于整数位置选择。
print(df.loc[0]) # 选择第一行
print(df.loc[0, '姓名']) # 选择第一行'姓名'列的值
print(df.loc[0:2, ['姓名', '年龄']]) # 选择0到2行(包含2),'姓名'和'年龄'列
print(df.iloc[0:3, 0:2]) # 选择前3行,前2列(基于位置)

条件过滤:

# 筛选年龄大于30的员工
older_employees = df[df['年龄'] > 30]
print(older_employees)

# 筛选城市是上海且薪资高于10000的员工
filtered_df = df[(df['城市'] == '上海') & (df['薪资'] > 10000)]
print(filtered_df)

5. 数据清洗与处理

这是数据分析中最耗时也最关键的一步。

缺失值处理:

# 检查缺失值
print(df.isnull().sum())

# 删除含有缺失值的行
# df_cleaned = df.dropna()

# 填充缺失值
# df_filled = df.fillna(value=0) # 用0填充所有缺失值
# df['年龄'].fillna(df['年龄'].mean(), inplace=True) # 用年龄均值填充年龄列的缺失值

数据类型转换:

# 将某一列转换为特定类型
# df['年龄'] = df['年龄'].astype(int)

重复值处理:

# 检查重复行
# print(df.duplicated().sum())
# 删除重复行
# df_no_duplicates = df.drop_duplicates()

6. 数据聚合与分组

groupby()是Pandas中最强大的功能之一,它允许你按照一个或多个列对数据进行分组,然后对每个组执行聚合操作(如求和、均值、计数等)。

# 按照城市分组,计算每个城市的平均薪资
avg_salary_by_city = df.groupby('城市')['薪资'].mean()
print(avg_salary_by_city)

# 按照城市和年龄分组,计算每个组的薪资总和
grouped_data = df.groupby(['城市', '年龄'])['薪资'].sum()
print(grouped_data)

# 可以同时应用多个聚合函数
agg_data = df.groupby('城市')['薪资'].agg(['mean', 'max', 'min', 'count'])
print(agg_data)

7. 数据合并与连接

当数据分散在多个DataFrame中时,你需要将它们合并起来。

df1 = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'value': np.random.randn(4)})
df2 = pd.DataFrame({'key': ['B', 'D', 'E', 'F'], 'value2': np.random.randn(4)})

# 内连接:只保留两个DataFrame中key都存在的行
merged_df = pd.merge(df1, df2, on='key', how='inner')
print(merged_df)

# 左连接:保留左边DataFrame的所有行,匹配右边DataFrame的行
left_merged_df = pd.merge(df1, df2, on='key', how='left')
print(left_merged_df)

# 拼接(Stacking):将多个DataFrame按行或列堆叠起来
df3 = pd.DataFrame({'key': ['G', 'H'], 'value': np.random.randn(2)})
concatenated_df = pd.concat([df1, df3], ignore_index=True)
print(concatenated_df)

Pandas数据清洗的常用技巧有哪些?

数据清洗,这活儿说起来简单,做起来往往是整个项目最磨人的部分。我的经验是,没有哪个数据集是“干净”的,总有些奇奇怪怪的脏数据等着你去处理。Pandas在这方面提供了很多趁手的工具。

除了前面提到的缺失值、重复值处理,还有几个点我觉得特别重要:

  1. 异常值检测与处理: 异常值可能是数据录入错误,也可能代表了真实的特殊情况。识别它们是第一步。常用的方法有基于统计(如3倍标准差、IQR范围)或可视化(箱线图、散点图)。Pandas本身没有直接的异常值检测函数,但你可以结合其统计功能轻松实现。

    # 假设我们想找出薪资的异常值
    Q1 = df['薪资'].quantile(0.25)
    Q3 = df['薪资'].quantile(0.75)
    IQR = Q3 - Q1
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    
    outliers = df[(df['薪资'] < lower_bound) | (df['薪资'] > upper_bound)]
    print("薪资异常值:\n", outliers)
    
    # 处理方式可以是删除、替换为均值/中位数,或者上限/下限值
    # df['薪资'] = np.where(df['薪资'] > upper_bound, upper_bound, df['薪资'])

    处理异常值需要谨慎,有时它们是宝贵的信息,比如高价值客户或系统故障。

  2. 文本数据清洗: 字符串列往往是最混乱的。大小写不一致、多余空格、特殊字符、错别字……这些都得处理。Pandas的str访问器非常强大。

    df['城市'] = df['城市'].str.strip() # 移除前后空格
    df['城市'] = df['城市'].str.lower() # 转换为小写
    df['姓名'] = df['姓名'].str.replace('张', 'ZHANG') # 替换字符
    # 使用正则表达式进行更复杂的匹配和替换
    # df['描述'] = df['描述'].str.replace(r'[^\w\s]', '', regex=True) # 移除所有非字母数字和空格的字符

    这里面有个小坑,如果你的字符串列里有NaN,直接调用str方法会报错,需要先填充或过滤掉缺失值。

  3. 日期时间数据处理: 日期时间格式不统一是常态。Pandas的to_datetime函数能智能地解析多种日期时间格式。

    # df['日期'] = pd.to_datetime(df['日期'], errors='coerce') # errors='coerce'会将无法解析的日期转换为NaT(Not a Time)
    # 提取年份、月份、星期几等
    # df['年份'] = df['日期'].dt.year
    # df['月份'] = df['日期'].dt.month

    处理日期时间时,时区问题也常常让人头疼,特别是在处理跨国数据时。Pandas提供了tz_localizetz_convert来处理这些。

  4. 数据标准化/归一化: 在进行机器学习前,往往需要将不同量纲的数值特征进行缩放。虽然这通常在Pandas之外(如scikit-learn)完成,但Pandas是数据准备的平台。

    # 简单的Min-Max标准化示例
    # df['薪资_normalized'] = (df['薪资'] - df['薪资'].min()) / (df['薪资'].max() - df['薪资'].min())

    这些技巧,用得多了自然熟练,但每次遇到新数据,我还是会先花大量时间在清洗上,毕竟“垃圾进,垃圾出”是数据分析的铁律。

Pandas如何进行数据聚合和分组分析?

数据聚合和分组分析是Pandas的灵魂所在,它允许我们从宏观角度理解数据,而不是纠结于每一行。groupby()方法就是实现这一点的核心。

想象一下,你有一堆销售数据,你可能想知道每个产品类别的总销售额,或者每个地区的平均订单价值。这就是groupby()的用武之地。

基本流程是:Split-Apply-Combine

  1. Split(拆分):根据一个或多个键(列)将DataFrame拆分成若干个组。
  2. Apply(应用):对每个组独立地应用一个函数(聚合、转换或过滤)。
  3. Combine(组合):将所有组的结果组合成一个新的DataFrame或Series。

最常见的应用是聚合函数:

# 假设我们有一个更复杂的销售数据
sales_data = {
    '产品类别': ['电子', '服装', '电子', '食品', '服装', '电子', '食品'],
    '地区': ['华东', '华南', '华东', '华北', '华南', '华东', '华北'],
    '销售额': [1200, 500, 1500, 300, 800, 1000, 450],
    '订单数量': [10, 5, 12, 3, 8, 9, 4]
}
sales_df = pd.DataFrame(sales_data)
print("原始销售数据:\n", sales_df)

# 按产品类别计算总销售额
total_sales_by_category = sales_df.groupby('产品类别')['销售额'].sum()
print("\n按产品类别总销售额:\n", total_sales_by_category)

# 按地区计算平均订单数量
avg_orders_by_region = sales_df.groupby('地区')['订单数量'].mean()
print("\n按地区平均订单数量:\n", avg_orders_by_region)

更进一步,你可以同时对多个列应用不同的聚合函数,使用agg()方法:

# 按产品类别和地区分组,同时计算销售额的总和、平均值和订单数量的总和
multi_agg = sales_df.groupby(['产品类别', '地区']).agg(
    总销售额=('销售额', 'sum'),
    平均销售额=('销售额', 'mean'),
    总订单数量=('订单数量', 'sum')
)
print("\n多重聚合结果:\n", multi_agg)

这里我用了Python 3.6+的f-string风格的agg语法,它让输出的列名更清晰,我个人觉得比传入字典的旧方式更直观。

除了聚合,groupby()还可以用于转换(transform)过滤(filter)

  • transform:对每个组应用一个函数,但返回的结果与原始DataFrame的索引对齐,常用于填充组内缺失值或进行组内标准化。
    # 计算每个产品类别销售额占该类别总销售额的比例
    sales_df['类别销售额占比'] = sales_df.groupby('产品类别')['销售额'].transform(lambda x: x / x.sum())
    print("\n带类别销售额占比的数据:\n", sales_df)
  • filter:根据组的某些特性来筛选组。
    # 筛选出总销售额超过2000的产品类别
    filtered_categories = sales_df.groupby('产品类别').filter(lambda x: x['销售额'].sum() > 2000)
    print("\n总销售额超过2000的产品类别数据:\n", filtered_categories)

    这些高级用法让groupby()变得极其灵活,能解决很多复杂的数据分析问题。我发现很多人刚开始用Pandas时,经常会尝试用循环来解决分组问题,但一旦掌握了groupby(),效率会提升好几个数量级。

Pandas在实际项目中常见的陷阱与最佳实践?

在实际项目中使用Pandas,我遇到过不少坑,也总结了一些经验。它确实强大,但用不好也容易“翻车”。

常见陷阱:

  1. 链式赋值警告(SettingWithCopyWarning): 这是新手最常遇到的问题之一。当你对一个DataFrame的“视图”进行修改时,Pandas会发出警告。

    # 错误示例:可能引发SettingWithCopyWarning
    # df_subset = df[df['年龄'] > 30]
    # df_subset['薪资'] = df_subset['薪资'] * 1.1 # 这里的修改可能不会反映到原始df,也可能报错

    最佳实践: 明确地使用.loc.copy()。如果你想创建一个独立的DataFrame副本,就用.copy();如果想在原始DataFrame上修改,且操作是基于条件选择的,就用.loc

    df_subset = df[df['年龄'] > 30].copy() # 明确复制一份
    df_subset['薪资'] = df_subset['薪资'] * 1.1
    
    # 在原始DataFrame上修改,使用.loc
    df.loc[df['年龄'] > 30, '薪资'] = df.loc[df['年龄'] > 30, '薪资'] * 1.1

    这个坑我踩过好几次,导致数据修改没生效,或者莫名其妙的错误。

  2. 性能问题: 对大型数据集使用循环(for循环、apply配合lambda函数)往往效率低下。

    # 性能差的示例:逐行处理
    # for index, row in df.iterrows():
    #     df.loc[index, '新列'] = row['列A'] + row['列B']

    最佳实践: 尽可能使用Pandas的向量化操作。Pandas底层是C语言实现的,向量化操作能充分利用CPU的并行计算能力。

    df['新列'] = df['列A'] + df['列B'] # 向量化操作

    如果必须使用apply,尽量用在Series上,或者确保你的函数是高度优化的。对于非常复杂的操作,考虑使用df.apply(..., axis=1),但要清楚这通常比向量化慢。更极致的性能需求,可以考虑numbamodin

  3. 内存占用: 大数据集可能导致内存不足。特别是字符串和日期时间列,它们在Pandas中可能比你想象的更占用内存。 最佳实践:

    • 选择合适的数据类型: 对于整数或浮点数,使用int8, int16, float32等更小的类型。df.info(memory_usage='deep')可以查看详细内存占用。
    • Categorical类型: 对于重复值较多的字符串列(如国家、城市),转换为category类型可以显著节省内存。
      df['城市'] = df['城市'].astype('category')
    • 分块读取: 对于超大型文件,使用pd.read_csv(..., chunksize=...)分块读取和处理数据。
  4. 索引管理不当: 索引是Pandas的强大之处,但如果处理不当,也可能导致问题,比如合并时索引不匹配。 最佳实践:

    • 在合并或拼接DataFrame时,明确指定on参数,或者在不需要索引时使用reset_index()
    • 如果索引有实际意义(如时间序列),充分利用它进行时间序列操作。

这些陷阱,说到底都是对Pandas底层机制理解不够深入造成的。多实践,多看官方文档,你会发现Pandas的设计哲学非常精妙。它不是一个简单的工具库,而是一个强大的数据处理框架,值得我们花时间去深入学习。

好了,本文到此结束,带大家了解了《PythonPandas数据处理入门指南》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多文章知识!

相关阅读
更多>
最新阅读
更多>
课程推荐
更多>