Pandas 数据处理基础入门

Pandas 数据处理基础入门

实验环境 : 华为云 FlexusX 实例 (Ubuntu 24.04, 8vCPU/16GiB)

Pandas 版本 : 2.1.4

实验日期 : 2026-06-29

作者: 腾讯开发者 - 华为云实战系列


目录

  • 实验背景
  • 环境准备
  • [实验1: 数据类型](#实验1: 数据类型)
  • [实验2: 数据读取](#实验2: 数据读取)
  • [实验3: 数据预览和基本操作](#实验3: 数据预览和基本操作)
  • [实验4: 数据选择](#实验4: 数据选择)
  • [实验5: 数据增删](#实验5: 数据增删)
  • [实验6: 数据填充](#实验6: 数据填充)
  • [实验7: 数据可视化](#实验7: 数据可视化)
  • 踩坑记录
  • 总结

实验背景

Pandas 是 Python 生态中最核心的数据分析库,提供了高性能、易用的数据结构和数据分析工具。本实验在华为云 FlexusX 实例上,通过 7 个递进实验,系统掌握 Pandas 的数据类型、读取、选择、增删、填充和可视化功能。

实验目标

  1. 理解 Pandas 的 7 种核心数据类型
  2. 掌握 CSV / 字典 / 数据库等多种数据读取方式
  3. 熟练使用 head() / tail() / info() / describe() 进行数据预览
  4. 掌握 loc / iloc / 条件筛选等数据选择方法
  5. 掌握新增 / 删除行列的操作
  6. 处理缺失值:固定值填充、前向/后向填充、插值
  7. 使用 Matplotlib 后端生成 4 种数据可视化图表

环境准备

华为云服务器配置

参数
实例类型 FlexusX x2e.8u.16g
CPU 8vCPU
内存 16GiB
操作系统 Ubuntu 24.04 server 64bit
网络 5 Mbit/s BGP
Python 3.12.3
Pandas 2.1.4

安装 Pandas

bash 复制代码
# 更新软件源并安装 Pandas (Ubuntu 24.04)
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq python3-pandas python3-matplotlib python3-seaborn

验证安装

python 复制代码
import pandas as pd
import numpy as np
import matplotlib
print(pd.__version__)   # 2.1.4
print(np.__version__)   # 1.26.4
print(matplotlib.__version__)  # 3.8.4

实验1: 数据类型 (Data Types)

Pandas 支持多种数据类型,了解它们是数据处理的基础。

1.1 创建不同数据类型的 Series

python 复制代码
import pandas as pd
import numpy as np

# 整数类型
s_int = pd.Series([1, 2, 3, 4, 5])
print(f"s_int dtype: {s_int.dtype}")  # int64

# 浮点类型
s_float = pd.Series([1.1, 2.2, 3.3, 4.4])
print(f"s_float dtype: {s_float.dtype}")  # float64

# 字符串类型 (object)
s_str = pd.Series(['apple', 'banana', 'cherry'])
print(f"s_str dtype: {s_str.dtype}")  # object

# 布尔类型
s_bool = pd.Series([True, False, True, True])
print(f"s_bool dtype: {s_bool.dtype}")  # bool

# 日期时间类型
s_datetime = pd.Series(pd.to_datetime(['2024-01-01', '2024-02-01', '2024-03-01']))
print(f"s_datetime dtype: {s_datetime.dtype}")  # datetime64[ns]

输出:

复制代码
s_int dtype: int64
s_float dtype: float64
s_str dtype: object
s_bool dtype: bool
s_datetime dtype: datetime64[ns]

1.2 DataFrame 各列的数据类型

python 复制代码
df = pd.read_csv('/tmp/employees.csv')
print(df.dtypes)

输出:

复制代码
name           object
age             int64
city           object
salary        float64
hire_date      object
department     object
dtype: object

1.3 数据类型转换

python 复制代码
# 将 age 列从 int64 转换为 float64
df['age'] = df['age'].astype('float64')
print('age列转换为float64:', df['age'].dtype)

# 将 city 列转换为分类类型 (节省内存)
df['city'] = df['city'].astype('category')
print('city列转换为category:', df['city'].dtype)
print('分类唯一值:', df['city'].cat.categories.tolist())

输出:

复制代码
age列转换为float64: float64
city列转换为category: category
分类唯一值: ['上海', '北京', '广州', '深圳']

Pandas 常用数据类型对照表

类型 说明 示例
int64 64位整数 1, 2, 3
float64 64位浮点数 1.1, 2.2
object 字符串/混合类型 'hello', 'world'
bool 布尔值 True, False
datetime64[ns] 日期时间 2024-01-01
category 分类变量 'A', 'B', 'C'
timedelta[ns] 时间差 days=1

实验2: 数据读取 (Data Reading)

2.1 读取 CSV 文件

python 复制代码
import pandas as pd

# 读取员工数据
df = pd.read_csv('/tmp/employees.csv')
print(f'数据形状: {df.shape}')
print(f'列名: {list(df.columns)}')
print('\n前5行数据:')
print(df.head())

输出:

复制代码
数据形状: (20, 6)
列名: ['name', 'age', 'city', 'salary', 'hire_date', 'department']

前5行数据:
  name  age city   salary   hire_date department
0   张三   28   北京  15000.0  2020-03-15        技术部
1   李四   32   上海  18000.0  2019-07-20        市场部
2   王五   25   北京  12000.0  2021-01-10        技术部
3   赵六   35   深圳  22000.0  2018-11-05        财务部
4   钱七   29   上海  16000.0  2020-09-18        市场部

2.2 读取时指定参数

python 复制代码
# 将 hire_date 列解析为日期类型
df2 = pd.read_csv('/tmp/employees.csv', index_col=0, parse_dates=['hire_date'])
print('设置hire_date为日期类型:')
print(df2.dtypes)

输出:

复制代码
设置hire_date为日期类型:
age                    int64
city                  object
salary               float64
hire_date     datetime64[ns]
department            object
dtype: object

2.3 从字典创建 DataFrame

python 复制代码
data = {'name': ['Alice', 'Bob', 'Charlie'], 'score': [85, 92, 78]}
df3 = pd.DataFrame(data)
print(df3)

输出:

复制代码
      name  score
0    Alice     85
1      Bob     92
2  Charlie     78

read_csv 常用参数

参数 说明
filepath_or_buffer 文件路径或 URL
sep 分隔符,默认 ,
header 列名行,默认 0 (第一行)
index_col 用作索引的列
usecols 选择读取的列
dtype 指定列的数据类型
parse_dates 解析为日期的列
na_values 识别为 NaN 的值

实验3: 数据预览和基本操作

3.1 数据预览

python 复制代码
# 前3行
print(df.head(3))

# 后3行
print(df.tail(3))

# 数据信息
print(df.info())

# 统计描述
print(df.describe())

输出:

复制代码
[前3行]
  name  age city   salary   hire_date department
0   张三   28   北京  15000.0  2020-03-15        技术部
1   李四   32   上海  18000.0  2019-07-20        市场部
2   王五   25   北京  12000.0  2021-01-10        技术部

[后3行]
   name  age city   salary   hire_date department
17  王二十   23   广州  11000.0  2022-01-05        人事部
18  李二一   31  NaN  18500.0  2019-08-22        市场部
19  赵二二   37   深圳  26000.0  2016-12-30        技术部

[数据信息]
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 20 entries, 0 to 19
Data columns (total 6 columns):
 #   Column      Non-Null Count  Dtype  
---  ------      --------------  -----  
 0   name        20 non-null     object 
 1   age         20 non-null     int64  
 2   city        18 non-null     object 
 3   salary      19 non-null     float64
 4   hire_date   20 non-null     object 
 5   department  20 non-null     object 
dtypes: float64(1), int64(1), object(4)
memory usage: 1.1+ KB

[统计描述]
             age        salary
count  20.000000     19.000000
mean   30.700000  18184.210526
std     4.878524   4497.562693
min    23.000000  11000.000000
25%    26.750000  14500.000000
50%    30.500000  18000.000000
75%    34.250000  21500.000000
max    40.000000  26000.000000

3.2 基本操作

python 复制代码
# 列访问
print(df['salary'].head())

# 新增列 (奖金 = 薪资 × 10%)
df['bonus'] = df['salary'] * 0.1
print(df[['name', 'salary', 'bonus']].head())

输出:

复制代码
[访问salary列 (前5个)]
0    15000.0
1    18000.0
2    12000.0
3    22000.0
4    16000.0
Name: salary, dtype: float64

[新增bonus列]
  name   salary   bonus
0   张三  15000.0  1500.0
1   李四  18000.0  1800.0
2   王五  12000.0  1200.0
3   赵六  22000.0  2200.0
4   钱七  16000.0  1600.0

实验4: 数据选择 (Data Selection)

4.1 列选择

python 复制代码
# 选择单列
print(df[['name', 'salary']].head())

4.2 行选择 - loc (标签索引)

python 复制代码
# 选择行标签 0~2,列 name/city/salary
print(df.loc[0:2, ['name', 'city', 'salary']])

输出:

复制代码
  name city   salary
0   张三   北京  15000.0
1   李四   上海  18000.0
2   王五   北京  12000.0

4.3 行选择 - iloc (位置索引)

python 复制代码
# 选择前2行,前3列
print(df.iloc[0:2, 0:3])

输出:

复制代码
  name  age city
0   张三   28   北京
1   李四   32   上海

4.4 条件选择

python 复制代码
# 筛选薪资 > 20000 的员工
print(df[df['salary'] > 20000][['name', 'salary']])

输出:

复制代码
   name   salary
3    赵六  22000.0
5    孙八  25000.0
11  赵十四  23000.0
14  周十七  21000.0
16  郑十九  24000.0
19  赵二二  26000.0

4.5 多条件选择

python 复制代码
# 北京且薪资 > 15000
print(df[(df['city'] == '北京') & (df['salary'] > 15000)][['name', 'city', 'salary']])

输出:

复制代码
   name city   salary
5    孙八   北京  25000.0
16  郑十九   北京  24000.0

loc vs iloc 对比

方法 索引类型 示例
loc 标签索引 df.loc[0:2] 包含标签 2
iloc 位置索引 df.iloc[0:2] 不包含位置 2
at 单个标签 df.at[0, 'name']
iat 单个位置 df.iat[0, 0]

实验5: 数据增删 (Data Addition/Deletion)

5.1 新增列

python 复制代码
df['level'] = ['P6', 'P7', 'P5', 'P8', 'P7', 'P9', 'P5', 'P7', 'P6', 'P8', 'P5', 'P9', 'P6', 'P5', 'P8', 'P7', 'P9', 'P4', 'P7', 'P9']
print(df[['name', 'level']].head())

5.2 新增行

python 复制代码
new_row = pd.DataFrame({
    'name': ['新员一'], 'age': [26], 'city': ['杭州'],
    'salary': [16000], 'hire_date': ['2023-01-01'], 'department': ['技术部']
})
df = pd.concat([df, new_row], ignore_index=True)
print('新增行后数据形状:', df.shape)  # (21, 7)

5.3 删除列

python 复制代码
df_drop = df.copy()
df_drop = df_drop.drop('level', axis=1)
print('删除level列后列名:', list(df_drop.columns))

5.4 删除行

python 复制代码
df_drop_rows = df.drop([0, 1]).reset_index(drop=True)
print('删除前2行后形状:', df_drop_rows.shape)  # (19, 7)

实验6: 数据填充 (Data Filling)

6.1 查找缺失值

python 复制代码
print('各列缺失值数量:')
print(df.isnull().sum())

输出:

复制代码
各列缺失值数量:
name          0
age           0
city          2
salary        1
hire_date     0
department    0
dtype: int64

6.2 填充缺失值 - 固定值

python 复制代码
df_fill = df.copy()

# 用平均值填充 age 的缺失值
df_fill['age'] = df_fill['age'].fillna(df_fill['age'].mean())

# 用 '未知' 填充 city 的缺失值
df_fill['city'] = df_fill['city'].fillna('未知')

# 用中位数填充 salary 的缺失值
df_fill['salary'] = df_fill['salary'].fillna(df_fill['salary'].median())

print('填充后缺失值:')
print(df_fill.isnull().sum())

输出:

复制代码
填充后缺失值:
name          0
age           0
city          0
salary        0
hire_date     0
department    0
dtype: int64

6.3 填充缺失值 - 前向/后向填充

python 复制代码
df_ffill = pd.DataFrame({'a': [1, None, None, 4, None, 6]})
print('使用前向填充:')
print(df_ffill['a'].ffill())  # 等价于 fillna(method='ffill')

输出:

复制代码
使用前向填充:
0    1.0
1    1.0
2    1.0
3    4.0
4    4.0
5    6.0
Name: a, dtype: float64

6.4 插值填充

python 复制代码
df_interp = pd.DataFrame({'value': [10, None, 30, None, 50]})
df_interp['value'] = df_interp['value'].interpolate()
print(df_interp)

输出:

复制代码
   value
0   10.0
1   20.0
2   30.0
3   40.0
4   50.0

缺失值处理策略

方法 函数 适用场景
删除缺失行 df.dropna() 缺失比例很小
固定值填充 df.fillna(value) 已知填充值
均值/中位数填充 df.fillna(df.mean()) 数值型数据
众数填充 df.fillna(df.mode()) 分类型数据
前向填充 df.ffill() 时间序列数据
后向填充 df.bfill() 时间序列数据
插值填充 df.interpolate() 连续数值数据

实验7: 数据可视化 (Data Visualization)

7.1 柱状图 - 各部门人数

python 复制代码
import matplotlib
matplotlib.use('Agg')  # 使用非交互式后端
import matplotlib.pyplot as plt

df = pd.read_csv('/tmp/employees.csv')
dept_counts = df['department'].value_counts()

fig, ax = plt.subplots(figsize=(8, 5))
dept_counts.plot(kind='bar', ax=ax)
ax.set_title('Department Distribution')
ax.set_ylabel('Count')
plt.tight_layout()
plt.savefig('/tmp/dept_bar.png')
print('柱状图已保存到 /tmp/dept_bar.png')
print(dept_counts)

输出:

复制代码
department
技术部    9
市场部    5
财务部    3
人事部    3
Name: count, dtype: int64

7.2 直方图 - 薪资分布

python 复制代码
fig, ax = plt.subplots(figsize=(8, 5))
df['salary'].plot(kind='hist', bins=10, ax=ax)
ax.set_title('Salary Distribution')
ax.set_xlabel('Salary')
plt.tight_layout()
plt.savefig('/tmp/salary_hist.png')
print('直方图已保存到 /tmp/salary_hist.png')

7.3 箱线图 - 各市薪资

python 复制代码
fig, ax = plt.subplots(figsize=(8, 5))
df.boxplot(column='salary', by='city', ax=ax)
plt.title('Salary by City')
plt.xticks(rotation=45)
plt.tight_layout()
plt.savefig('/tmp/salary_box.png')
print('箱线图已保存到 /tmp/salary_box.png')

7.4 折线图 - 月度销售趋势

python 复制代码
sales = pd.read_csv('/tmp/sales.csv')
monthly = sales.groupby('month')['sales'].sum()
print(monthly)

fig, ax = plt.subplots(figsize=(8, 5))
monthly.plot(kind='line', marker='o', ax=ax)
ax.set_title('Monthly Sales Trend')
ax.set_ylabel('Sales')
plt.tight_layout()
plt.savefig('/tmp/sales_line.png')
print('折线图已保存到 /tmp/sales_line.png')

输出:

复制代码
month
2024-01    290000
2024-02    325000
2024-03    315000
2024-04    347000
Name: sales, dtype: int64

Pandas 内置绘图函数

图表类型 函数 说明
折线图 df.plot(kind='line') 趋势分析
柱状图 df.plot(kind='bar') 分类比较
直方图 df.plot(kind='hist') 分布分析
箱线图 df.boxplot() 离群值检测
散点图 df.plot(kind='scatter') 相关性分析
饼图 df.plot(kind='pie') 占比分析
面积图 df.plot(kind='area') 累积趋势

踩坑记录

坑1: fillna(method='ffill') 已弃用

错误信息:

复制代码
FutureWarning: DataFrame.fillna with 'method' is deprecated and will raise in a future version.

解决方案:

python 复制代码
# 旧写法 (已弃用)
df.fillna(method='ffill')

# 新写法 (推荐)
df.ffill()
df.bfill()

坑2: Matplotlib 中文显示乱码

问题: 在 Ubuntu Server 上生成图表时,中文显示为方框。

解决方案:

python 复制代码
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['DejaVu Sans', 'SimHei', 'WenQuanYi Micro Hei']
plt.rcParams['axes.unicode_minus'] = False

坑3: info() 输出不直接显示

问题 : df.info() 打印到 stdout,无法直接获取字符串。

解决方案:

python 复制代码
# 方法1: 重定向到缓冲区
import io
buffer = io.StringIO()
df.info(buf=buffer)
info_str = buffer.getvalue()

# 方法2: 使用 df.memory_usage(deep=True)

总结

通过本实验,在华为云 FlexusX 实例上完成了 Pandas 数据处理的 7 个核心实验:

  1. 数据类型 : 掌握 int64 / float64 / object / bool / datetime64[ns] / category 等类型及转换方法
  2. 数据读取 : 熟练使用 read_csv 读取 CSV 文件,并掌握常用参数
  3. 数据预览 : 使用 head() / tail() / info() / describe() 快速了解数据
  4. 数据选择 : 掌握 loc (标签) / iloc (位置) / 条件筛选三种选择方式
  5. 数据增删 : 使用 assign / concat 新增行列,使用 drop 删除行列
  6. 数据填充: 处理缺失值的 4 种策略:固定值、前向/后向填充、插值
  7. 数据可视化: 使用 Matplotlib 后端生成柱状图、直方图、箱线图、折线图

后续学习方向

  • 数据合并 : merge / join / concat
  • 数据透视 : pivot_table / groupby
  • 时间序列 : resample / rolling / shift
  • 高性能优化 : eval / query / Categorical
  • 大数据处理 : Dask / Modin (兼容 Pandas API)

附录: 实验数据说明

employees.csv (员工数据)

列名 类型 说明
name object 员工姓名
age int64 年龄
city object 工作城市
salary float64 月薪
hire_date object 入职日期
department object 所属部门

sales.csv (销售数据)

列名 类型 说明
month object 月份
product object 产品名称
category object 产品类别
sales int64 销售额
profit int64 利润

实验服务器 : 华为云 FlexusX x2e.8u.16g (120.46.31.149)

实验日期 : 2026-06-29

完整代码 : GitHub 仓库链接

下一篇: 《Matplotlib 数据可视化进阶实战》