📚 Pandas数据分析完整学习指南

💡 核心定位:Pandas是Python中最强大的数据分析库,专门用于处理结构化数据,基于NumPy构建


📑 目录结构

  1. Pandas核心数据结构
  2. Series详解
  3. Series字符串操作
  4. Series其他常用方法
  5. DataFrame详解
  6. DataFrame高级操作
  7. 数据读取与存储
  8. 数据库连接
  9. 知识点速查表

1. Pandas核心数据结构

1.1 Pandas简介

📌 核心概念
Pandas提供两种核心数据结构用于数据分析:

  • Series:一维数组 + 标签(类似带索引的列表)
  • DataFrame:二维数组 + 行标签 + 列名称(类似Excel表格)

💡 知识点:Pandas的四大功能

  1. 读取数据
  2. 数据处理
  3. 数据分析
  4. 数据可视化

📝 代码示例:导入Pandas

import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')  # 忽略警告信息

⚠️ 注意事项

  • Pandas基于NumPy构建,因此继承了NumPy的许多特性
  • 通常使用pd作为Pandas的别名(行业标准)
  • 建议同时导入NumPy,因为很多操作需要配合使用

2. Series详解

2.1 Series基础概念

📌 核心概念
Series是一维的数组加标签,可以理解为Excel表格中的一列数据,每个数据都有对应的行索引。

🔧 函数:pd.Series()

📊 参数说明

参数 类型 说明 默认值
data list/tuple/dict/ndarray 数据源 必填
index list/array 行索引标签 0开始的整数
dtype dtype 数据类型 自动推断
name str Series名称 None

📝 代码示例:创建Series

# 方法1:从列表创建
data = [1, 2, 3, 4]
s1 = pd.Series(data=data, index=list('abcd'))
print(s1)
# 输出:
# a    1
# b    2
# c    3
# d    4
# dtype: int64

# 方法2:从字典创建(推荐)
dic = {'lisa': 80, 'cc': 90, 'john': 100}
s2 = pd.Series(data=dic)
print(s2)
# 输出:
# lisa     80
# cc       90
# john    100
# dtype: int64

# 方法3:从NumPy数组创建
arr = np.array([1, 2, 3, 4])
s3 = pd.Series(data=arr, index=list('abcd'))

💎 最佳实践

✅ 推荐:使用字典创建Series,键自动成为索引
s = pd.Series({'name': 'Lisa', 'age': 18})

❌ 避免:索引长度与数据长度不匹配
s = pd.Series([1, 2, 3], index=['a', 'b'])  # 会报错

2.2 Series数据访问

💡 知识点:Series的两种索引方式

  1. 位置索引:使用整数位置(从0开始)
  2. 标签索引:使用自定义的索引标签

📝 代码示例:数据访问

s2 = pd.Series({'lisa': 80, 'cc': 90, 'john': 100})

# 位置索引访问
print(s2[0])        # 输出:80(第一个元素)

# 标签索引访问
print(s2['lisa'])   # 输出:80(通过标签访问)

# 多个元素访问
print(s2[['cc', 'john']])
# 输出:
# cc      90
# john    100
# dtype: int64

2.3 Series属性

📊 常用属性列表

属性 说明 示例
ndim 维度(Series固定为1) s.ndim
shape 形状(元素个数,) s.shape
size 元素总数 s.size
dtype 数据类型 s.dtype
index 行索引对象 s.index
values 值(返回NumPy数组) s.values

📝 代码示例:属性使用

s2 = pd.Series({'lisa': 80, 'cc': 90, 'john': 100})

print('维度:', s2.ndim)           # 输出:1
print('形状:', s2.shape)          # 输出:(3,)
print('元素个数:', s2.size)       # 输出:3
print('数据类型:', s2.dtype)      # 输出:int64
print('行索引:', s2.index)        # 输出:Index(['lisa', 'cc', 'john'], dtype='object')
print('值:', s2.values)           # 输出:[ 80  90 100]

2.4 Series继承NumPy的特性

💡 知识点:Series支持NumPy操作

📝 代码示例:NumPy风格操作

s2 = pd.Series({'lisa': 80, 'cc': 90, 'john': 100})

# 1. 掩码操作(布尔索引)
print('取出>=80的数据:\n', s2[s2 >= 80])
# 输出:
# lisa     80
# cc       90
# john    100

# 2. 切片操作
print('取出cc和john的成绩:\n', s2[['cc', 'john']])

# 3. 统计函数
print('计算成绩均值:', s2.mean())      # 输出:90.0
print('最大值:', s2.max())             # 输出:100
print('最小值:', s2.min())             # 输出:80
print('标准差:', s2.std())             # 输出:10.0
print('求和:', s2.sum())               # 输出:270

🔗 关联知识
→ 3. Series字符串操作
→ 4. Series其他常用方法


3. Series字符串操作

3.1 字符串操作基础

📌 核心概念
所有Series字符串操作都通过series.str.函数名()的形式调用,这是Pandas提供的向量化字符串操作接口。

⚠️ 注意事项

  • 必须使用.str访问器才能调用字符串方法
  • 字符串操作返回新的Series,不修改原数据(除非赋值)
  • 只能用于字符串类型的Series

3.2 常用字符串方法

📊 字符串方法速查表

方法 功能 返回值 示例
str.strip() 去除首尾指定字符 Series s.str.strip('()+ ')
str.split() 按分隔符分割 Series/DataFrame s.str.split('-')
str.replace() 替换子串 Series s.str.replace('old', 'new')
str.contains() 检查是否包含 布尔Series s.str.contains('关键词')
str.count() 统计子串出现次数 Series s.str.count('a')
str.len() 计算字符串长度 Series s.str.len()
str.find() 查找子串位置 Series s.str.find('x')

3.3 strip() - 去除首尾字符

🔧 函数:series.str.strip()

📝 代码示例

data = ['Tom', ' Jerry)', '(Tyke+', 'Spark']
s1 = pd.Series(data)

# 去除首尾的括号、加号和空格
s1 = s1.str.strip('()+ ')
print(s1)
# 输出:
# 0      Tom
# 1    Jerry
# 2     Tyke
# 3    Spark

# 去除首尾等号
data2 = ['Tom-Zhang', '====Jerry-Li', '===Tyke-Xiong===', 'Spark-Zhao====']
s2 = pd.Series(data2)
s2 = s2.str.strip('=')
print(s2)
# 输出:
# 0       Tom-Zhang
# 1       Jerry-Li
# 2    Tyke-Xiong
# 3    Spark-Zhao

💎 最佳实践

✅ 推荐:链式调用多个字符串方法
s = s.str.strip().str.lower().str.replace(' ', '_')

❌ 避免:忘记使用.str访问器
s = s.strip()  # 错误!会报错

3.4 split() - 字符串分割

🔧 函数:series.str.split()

📊 参数说明

参数 类型 说明 默认值
pat str 分隔符 空格
expand bool 是否展开为DataFrame False
n int 最大分割次数 -1(全部)

📝 代码示例

s2 = pd.Series(['Tom-Zhang', 'Jerry-Li', 'Tyke-Xiong', 'Spark-Zhao'])

# 基础分割(返回列表)
result1 = s2.str.split('-')
print(result1)
# 输出:
# 0     [Tom, Zhang]
# 1     [Jerry, Li]
# 2     [Tyke, Xiong]
# 3    [Spark, Zhao]

# 展开为DataFrame(推荐)
result2 = s2.str.split('-', expand=True)
print(result2)
# 输出:
#        0      1
# 0    Tom  Zhang
# 1  Jerry     Li
# 2   Tyke  Xiong
# 3  Spark   Zhao

# 设置列名
df = s2.str.split('-', expand=True)
df.columns = ['姓', '名']

🎯 应用场景:地理位置分割

s3 = pd.Series(['北京市-昌平区', '北京市-海淀区', '北京市-东城区'])
df1 = s3.str.split('-', expand=True)
df1.columns = ['城市', '片区']
print(df1)
# 输出:
#     城市   片区
# 0  北京市  昌平区
# 1  北京市  海淀区
# 2  北京市  东城区

3.5 replace() - 字符串替换

🔧 函数:series.str.replace()

📝 代码示例

s4 = pd.Series(['cc', 'lisa', 'john'])

# 替换字符串
s4 = s4.str.replace('cc', 'ch')
print(s4)
# 输出:
# 0      ch
# 1    lisa
# 2    john

# 实际应用:清理地铁站名称
s5 = pd.Series(['望京地铁站', '平安里地铁站', '西直门地铁站', '望京'])
s5 = s5.str.replace('地铁站', '')
print(s5)
# 输出:
# 0     望京
# 1    平安里
# 2    西直门
# 3     望京

3.6 contains() - 包含检查

🔧 函数:series.str.contains()

📊 参数说明

参数 类型 说明 默认值
pat str 搜索模式(支持正则) 必填
case bool 是否区分大小写 True
regex bool 是否使用正则表达式 True

📝 代码示例

s4 = pd.Series(['ch', 'lisa', 'john'])

# 基础包含检查
result = s4[s4.str.contains('lisa')]
print(result)
# 输出:
# 1    lisa

# 不区分大小写
emails = pd.Series(['user@example.com', 'admin@test.org', 'Support@ai.com'])
result = emails[emails.str.contains('admin|support', case=False)]
print(result)
# 输出:
# 1    admin@test.org
# 2    Support@ai.com

# 实际应用:筛选地点
s6 = s5[s5.str.contains('望京')]
print(s6)
# 输出:
# 0    望京
# 3    望京

3.7 count() - 统计子串出现次数

🔧 函数:series.str.count()

📝 代码示例

s4 = pd.Series(['ch', 'lisa', 'john'])

# 统计字符'c'出现的次数
result = s4.str.count('c')
print(result)
# 输出:
# 0    1
# 1    0
# 2    0

# 实际应用:统计DNA序列
dna = pd.Series(['AGCTAG', 'TTAGAC', 'GGGAGG'])
ag_count = dna.str.count('AG')
print(ag_count)
# 输出:
# 0    2
# 1    1
# 2    1

3.8 len() - 计算字符串长度

🔧 函数:series.str.len()

📝 代码示例

s4 = pd.Series(['ch', 'lisa', 'john'])

# 计算每个字符串的长度
lengths = s4.str.len()
print(lengths)
# 输出:
# 0    2
# 1    4
# 2    4

# 实际应用:验证学号长度
s2 = pd.Series(['20130101', '201301', '20130104', '20130106'])
invalid = s2[s2.str.len() != 8]
print('不合规的学号:\n', invalid)
# 输出:
# 1    201301

3.9 find() - 查找子串位置

🔧 函数:series.str.find()

💡 知识点:返回值规则

  • 找到:返回第一次出现的索引位置(从0开始)
  • 未找到:返回-1

📝 代码示例

s4 = pd.Series(['ch', 'lisa', 'john'])

# 查找字符'c'的位置
positions = s4.str.find('c')
print(positions)
# 输出:
# 0    0  ('ch'中'c'在位置0)
# 1   -1  ('lisa'中没有'c')
# 2   -1  ('john'中没有'c')

# 实际应用:筛选以'A'开头的数据
codes = pd.Series(['A100', 'B000', 'C300', 'A250'])
a_codes = codes[codes.str.find('A') == 0]
print(a_codes)
# 输出:
# 0    A100
# 3    A250

3.10 字符串索引

💡 知识点:直接索引字符

📝 代码示例

s1 = pd.Series(['Tom', 'Jerry', 'Tyke', 'Spark'])

# 截取首字母
first_letters = s1.str[0]
print(first_letters)
# 输出:
# 0    T
# 1    J
# 2    T
# 3    S

# 截取前三个字符
first_three = s1.str[0:3]
print(first_three)
# 输出:
# 0    Tom
# 1    Jer
# 2    Tyk
# 3    Spa

3.11 综合案例

🎯 案例1:公司福利统计

# 统计每家公司福利的个数
s1 = pd.Series(
    data=['五险一金,餐补,年终奖',
          '五险一金,下午茶,全勤奖,带薪休假',
          '五险一金,下午茶,全勤奖,带薪休假,定期体检,团建'],
    index=list('ABC')
)

# 方法:统计逗号数量+1
welfare_count = s1.str.count(',') + 1
print(welfare_count)
# 输出:
# A    3
# B    4
# C    6

🎯 案例2:学号验证

# 找到学号不合规的数据
s2 = pd.Series(['20130101', '201301', '20130104', '20130106'])
invalid_ids = s2[s2.str.len() != 8]
print('不合规学号:\n', invalid_ids)
# 输出:
# 1    201301

🎯 案例3:邮箱筛选

# 检查是否包含"admin"或"support"(不区分大小写)
emails = pd.Series(['user@example.com', 'admin@test.org', 'Support@ai.com'])
admin_emails = emails[emails.str.contains('admin|support', case=False)]
print(admin_emails)
# 输出:
# 1    admin@test.org
# 2    Support@ai.com

🔗 关联知识
→ 4. Series其他常用方法
→ 5. DataFrame详解


4. Series其他常用方法

4.1 isin() - 成员检查

🔧 函数:series.isin()

📌 核心概念
检查Series中的每个元素是否在给定的列表中,返回布尔Series,常用于按条件筛选数据。

📝 代码示例

s1 = pd.Series(['北京', '上海', '北京', '天津', '北京', '重庆', '上海', '重庆'])

# 筛选开设产品线的城市
target_cities = ['北京', '上海', '重庆']
result = s1[s1.isin(target_cities)]
print(result)
# 输出:
# 0    北京
# 1    上海
# 2    北京
# 4    北京
# 5    重庆
# 6    上海
# 7    重庆

# 实际应用:筛选已知性别
gender = pd.Series(['男', '女', '未统计', '男', '男', '女', '未统计'])
known_gender = gender[gender.isin(['男', '女'])]
print(known_gender)
# 输出:
# 0    男
# 1    女
# 3    男
# 4    男
# 5    女

💎 最佳实践

✅ 推荐:使用isin()进行多值筛选
df = df[df['city'].isin(['北京', '上海', '深圳'])]

❌ 避免:使用多个or条件
df = df[(df['city']=='北京') | (df['city']=='上海') | (df['city']=='深圳')]  # 冗长

4.2 unique() - 去重

🔧 函数:series.unique()

📌 核心概念
返回Series中所有唯一值组成的NumPy数组,用于查看数据中有哪些不同的类别。

📝 代码示例

gender = pd.Series(['男', '女', '未统计', '男', '男', '女', '未统计'])

# 查看有哪些类别
categories = gender.unique()
print('有哪些类别:', categories)
# 输出:['男' '女' '未统计']

# 数据清洗后再去重
data_info = pd.Series(
    ['经理', '本科', '经理 ', '初中', '博士', '专科',
     '专科', '博士', '博士', '本科', '专科', '本科', '专科', '本科'],
    name='学历'
)

# 去掉首尾空格
data_info = data_info.str.strip()
# 去掉非学历数据
data_info = data_info[data_info != '经理']
# 查看学历类别
print('学历类别:', data_info.unique())
# 输出:['本科' '初中' '博士' '专科']

4.3 nunique() - 唯一值计数

🔧 函数:series.nunique()

📌 核心概念
返回Series中唯一值的数量(去重后的计数),常用于统计类别数量。

📝 代码示例

gender = pd.Series(['男', '女', '男', '男', '女'])

# 统计类别数量
n_categories = gender.nunique()
print('一共有几个类别:', n_categories)
# 输出:2

4.4 value_counts() - 分类计数

🔧 函数:series.value_counts()

📊 参数说明

参数 类型 说明 默认值
normalize bool 是否返回占比 False
sort bool 是否排序 True
ascending bool 升序还是降序 False
dropna bool 是否排除缺失值 True

📝 代码示例

gender = pd.Series(['男', '女', '男', '男', '女'])

# 统计每个类别的数量
counts = gender.value_counts()
print('每个类别多少人:\n', counts)
# 输出:
# 男    3
# 女    2

# 计算占比
proportions = gender.value_counts(normalize=True)
print('男女占比:\n', proportions)
# 输出:
# 男    0.6
# 女    0.4

# 或者手动计算占比
proportions2 = gender.value_counts() / gender.size
print(proportions2)
# 输出:
# 男    0.6
# 女    0.4

🎯 应用场景:学历统计

data_info = pd.Series(
    ['本科', '初中', '博士', '专科', '专科', '博士', '博士', '本科', '专科', '本科', '专科', '本科'],
    name='学历'
)

# 查看各学历人数
print('各学历人数:\n', data_info.value_counts())
# 输出:
# 本科    4
# 专科    4
# 博士    3
# 初中    1

# 查看各学历占比
print('各学历占比:\n', data_info.value_counts(normalize=True))
# 输出:
# 本科    0.333333
# 专科    0.333333
# 博士    0.250000
# 初中    0.083333

4.5 map() - 映射转换

🔧 函数:series.map()

📌 核心概念
根据字典或函数对Series中的每个值进行一对一映射转换,常用于数据编码和分类转换。

📊 参数说明

参数 类型 说明
arg dict/function 映射规则(字典或函数)

📝 代码示例:城市等级映射

s1 = pd.Series(['北京', '上海', '北京', '天津', '北京', '重庆', '上海', '重庆'])

# 定义映射关系
city_map = {
    '北京': '一线城市',
    '上海': '一线城市',
    '天津': '二线城市',
    '重庆': '二线城市',
}

# 应用映射
s1 = s1.map(city_map)
print(s1)
# 输出:
# 0    一线城市
# 1    一线城市
# 2    一线城市
# 3    二线城市
# 4    一线城市
# 5    二线城市
# 6    一线城市
# 7    二线城市

🎯 应用场景:用户行为编码

# 用户行为数据:1-浏览 2-加购 3-收藏 4-购买
user_actions = pd.Series([1, 1, 2, 3, 4, 2, 1])

# 定义映射关系
actions_map = {
    1: 'pv',       # page view 浏览
    2: 'cart',     # 加购物车
    3: 'collect',  # 收藏
    4: 'buy'       # 购买
}

# 应用映射
user_actions = user_actions.map(actions_map)
print(user_actions)
# 输出:
# 0        pv
# 1        pv
# 2      cart
# 3   collect
# 4       buy
# 5      cart
# 6        pv

💎 最佳实践

✅ 推荐:使用map()进行分类编码
df['level'] = df['score'].map({1: '低', 2: '中', 3: '高'})

❌ 避免:使用多个if-else
# 不推荐的写法
def classify(x):
    if x == 1: return '低'
    elif x == 2: return '中'
    else: return '高'

4.6 shift() - 数据偏移

🔧 函数:series.shift()

📊 参数说明

参数 类型 说明 默认值
periods int 偏移量(正数向下,负数向上) 1
fill_value scalar 填充值 NaN

📌 核心概念
将Series中的数据向上或向下移动指定位置,常用于计算环比、同比等时间序列分析。

📝 代码示例:基础偏移

s2 = pd.Series(
    [11, 22, 33, 44, 55], 
    index=['一月', '二月', '三月', '四月', '五月']
)

# 向下偏移1位(正数)
shifted_down = s2.shift(1)
print(shifted_down)
# 输出:
# 一月    NaN
# 二月   11.0
# 三月   22.0
# 四月   33.0
# 五月   44.0

# 向上偏移1位(负数)
shifted_up = s2.shift(-1)
print(shifted_up)
# 输出:
# 一月   22.0
# 二月   33.0
# 三月   44.0
# 四月   55.0
# 五月    NaN

🎯 应用场景:计算月环比

s2 = pd.Series(
    [11, 22, 33, 44, 55], 
    index=['一月', '二月', '三月', '四月', '五月']
)

# 月环比 = (本月 - 上月) / 上月
# 例如:二月环比 = (22 - 11) / 11 = 1.0 = 100%增长
mom_growth = (s2 - s2.shift(1)) / s2.shift(1)
print('月环比:\n', mom_growth)
# 输出:
# 一月         NaN
# 二月    1.000000  (增长100%)
# 三月    0.500000  (增长50%)
# 四月    0.333333  (增长33.3%)
# 五月    0.250000  (增长25%)

💡 知识点:环比计算公式

  • 月环比 = (本月 - 上月) / 上月
  • 正数表示增长,负数表示下降
  • 例如:0.25 表示增长25%,-0.1 表示下降10%

🔗 关联知识
→ 5. DataFrame详解
→ 7. 数据读取与存储


5. DataFrame详解

5.1 DataFrame基础概念

📌 核心概念
DataFrame是二维的数组加行标签和列名称,可以理解为Excel表格或SQL数据表,是Pandas中最常用的数据结构。

💡 知识点:DataFrame的组成

  • 行索引(index):每一行的标签
  • 列名(columns):每一列的名称
  • 数据(values):实际的数据内容(NumPy数组)

🔧 函数:pd.DataFrame()

📊 参数说明

参数 类型 说明 默认值
data dict/list/ndarray 数据源 必填
index list/array 行索引 0开始的整数
columns list 列名 自动生成
dtype dtype 数据类型 自动推断

5.2 创建DataFrame的三种方式

📝 方法1:从NumPy数组创建

import numpy as np
import pandas as pd

# 创建随机数据
np.random.seed(123)
data = np.random.randint(1, 100, 24).reshape(6, 4)

# 定义行索引和列名
row_index = np.arange(2001, 2007, 1).astype(str)
col_index = ['语文', '数学', '英语', '物理']

# 创建DataFrame
df1 = pd.DataFrame(
    data=data,
    index=row_index,
    columns=col_index
)
print(df1)
# 输出:
#       语文  数学  英语  物理
# 2001  67  93  99  18
# 2002  84  58  87  98
# 2003  97  48  13  93
# 2004  89  84  28  10
# 2005  94  72  84  45
# 2006  39  60  75  39

📝 方法2:从字典创建(推荐)

# 字典的key是列名,value是列数据
dic = {
    '姓名': ['lisa', 'cc', 'john', 'lili'],
    '年龄': [18, 21, 20, 19],
    '语文成绩': [98, 95, 59, 75]
}

df2 = pd.DataFrame(data=dic, index=[5, 6, 7, 8])
print(df2)
# 输出:
#     姓名  年龄  语文成绩
# 5  lisa  18    98
# 6    cc  21    95
# 7  john  20    59
# 8  lili  19    75

📝 方法3:从嵌套列表创建

# 每个子列表代表一行数据
data1 = [
    ['lisa', 18, 98],
    ['cc', 21, 95],
    ['john', 20, 59],
    ['lili', 19, 75]
]

df3 = pd.DataFrame(data=data1, columns=['姓名', '年龄', '语文成绩'])
print(df3)
# 输出:
#     姓名  年龄  语文成绩
# 0  lisa  18    98
# 1    cc  21    95
# 2  john  20    59
# 3  lili  19    75

💎 最佳实践

✅ 推荐:使用字典创建DataFrame(列名清晰)
df = pd.DataFrame({'name': ['A', 'B'], 'age': [20, 21]})

❌ 避免:使用嵌套列表但不指定列名
df = pd.DataFrame([['A', 20], ['B', 21]])  # 列名不清晰

5.3 DataFrame属性

📊 常用属性列表

属性 说明 示例
shape 形状(行数, 列数) df.shape
ndim 维度(固定为2) df.ndim
size 元素总数 df.size
dtypes 每列的数据类型 df.dtypes
index 行索引对象 df.index
columns 列名对象 df.columns
values 值(NumPy数组) df.values

📝 代码示例

df1 = pd.DataFrame({
    '语文': [67, 84, 97],
    '数学': [93, 58, 48],
    '英语': [99, 87, 13]
}, index=['2001', '2002', '2003'])

print('df1的形状:', df1.shape)          # 输出:(3, 3)
print('df1的维度:', df1.ndim)           # 输出:2
print('df1的元素个数:', df1.size)       # 输出:9
print('df1的数据类型:\n', df1.dtypes)   
# 输出:
# 语文    int64
# 数学    int64
# 英语    int64

print('df1的行索引:', df1.index)        # 输出:Index(['2001', '2002', '2003'])
print('df1的列名:', df1.columns)        # 输出:Index(['语文', '数学', '英语'])
print('df1的值:\n', df1.values)
# 输出:
# [[67 93 99]
#  [84 58 87]
#  [97 48 13]]

5.4 DataFrame数据查询

5.4.1 查询列数据

💡 知识点:两种列访问方式

  1. 方括号访问df['列名']df[['列1', '列2']]
  2. 属性访问df.列名(仅适用于列名是合法Python标识符的情况)

📝 代码示例

df1 = pd.DataFrame({
    '语文': [67, 84, 97],
    '数学': [93, 58, 48],
    '英语': [99, 87, 13],
    '物理': [18, 98, 93]
}, index=['2001', '2002', '2003'])

# 查询单列(返回Series)
print(df1['语文'])
# 或
print(df1.语文)
# 输出:
# 2001    67
# 2002    84
# 2003    97

# 查询多列(返回DataFrame)
print(df1[['语文', '英语']])
# 输出:
#       语文  英语
# 2001  67  99
# 2002  84  87
# 2003  97  13

⚠️ 注意事项

  • 单列查询返回Series,多列查询返回DataFrame
  • 属性访问方式不能用于列名包含空格或特殊字符的情况
  • 多列查询必须使用双层方括号[[]]
5.4.2 查询行数据

💡 知识点:行切片
使用切片语法df[start:end:step]可以按行索引位置查询数据。

📝 代码示例

# 查询前两行
print(df1[0:2])
# 输出:
#       语文  数学  英语  物理
# 2001  67  93  99  18
# 2002  84  58  87  98

# 查询奇数行(0, 2, 4...)
print(df1[0:5:2])
# 输出:
#       语文  数学  英语  物理
# 2001  67  93  99  18
# 2003  97  48  13  93
5.4.3 iloc和loc定位

📌 核心概念

  • iloc:基于整数位置的索引(integer location),前闭后开
  • loc:基于标签的索引(label location),前闭后闭

🔍 对比说明

方法 索引方式 区间规则 使用场景
iloc 整数位置 前闭后开[) 按位置查询
loc 标签名称 前闭后闭[] 按名称查询

📝 代码示例

df1 = pd.DataFrame({
    '语文': [67, 84, 97, 89, 94, 39],
    '数学': [93, 58, 48, 84, 72, 60],
    '英语': [99, 87, 13, 28, 84, 75],
    '物理': [18, 98, 93, 10, 45, 39]
}, index=['2001', '2002', '2003', '2004', '2005', '2006'])

# iloc:前两行,前两列
print(df1.iloc[0:2, 0:2])
# 输出:
#       语文  数学
# 2001  67  93
# 2002  84  58

# loc:前两行,前两列(都能取到)
print(df1.loc['2001':'2002', '语文':'英语'])
# 输出:
#       语文  数学  英语
# 2001  67  93  99
# 2002  84  58  87

# loc:使用列表指定具体的行和列
print(df1.loc[['2001', '2002'], ['语文', '英语']])
# 输出:
#       语文  英语
# 2001  67  99
# 2002  84  87
5.4.4 条件查询

💡 知识点:布尔索引
使用条件表达式创建布尔Series,然后用于筛选数据。

📝 代码示例

# 查询语文成绩大于60分的数据
print(df1[df1['语文'] > 60])
# 或
print(df1.loc[df1['语文'] > 60])
# 输出:
#       语文  数学  英语  物理
# 2001  67  93  99  18
# 2002  84  58  87  98
# 2003  97  48  13  93
# 2004  89  84  28  10
# 2005  94  72  84  45

# 查询Lisa的语文成绩
df2 = pd.DataFrame({
    '姓名': ['lisa', 'cc', 'john', 'lili'],
    '年龄': [18, 21, 20, 19],
    '语文成绩': [98, 95, 59, 75]
}, index=[5, 6, 7, 8])

result = df2.loc[df2['姓名'] == 'lisa', '语文成绩']
print(result)
# 输出:
# 5    98

💎 最佳实践

✅ 推荐:使用loc进行条件查询
df.loc[df['age'] > 18, ['name', 'score']]

❌ 避免:链式索引(可能产生警告)
df[df['age'] > 18]['name']  # 不推荐

5.5 DataFrame数据修改

5.5.1 新增列

📝 代码示例

df1 = pd.DataFrame({
    '语文': [67, 84, 97],
    '数学': [93, 58, 48],
    '英语': [99, 87, 13]
}, index=['2001', '2002', '2003'])

# 新增化学成绩列
np.random.seed(123)
df1['化学'] = np.random.randint(20, 100, 3)
print(df1)
# 输出:
#       语文  数学  英语  化学
# 2001  67  93  99  86
# 2002  84  58  87  98
# 2003  97  48  13  97

# 新增行总分列
df1['row_sum'] = df1.sum(axis=1)
print(df1)
# 输出:
#       语文  数学  英语  化学  row_sum
# 2001  67  93  99  86     345
# 2002  84  58  87  98     327
# 2003  97  48  13  97     255
5.5.2 新增行

📝 代码示例

# 新增一行数据
df1.loc['2004'] = [90, 60, 100, 50, 300]
print(df1)
# 输出:
#       语文  数学  英语  化学  row_sum
# 2001  67  93  99  86     345
# 2002  84  58  87  98     327
# 2003  97  48  13  97     255
# 2004  90  60 100  50     300

# 新增列总和行
df1.loc['col_sum'] = df1.sum(axis=0)
print(df1)
# 输出:
#          语文   数学   英语   化学  row_sum
# 2001      67   93   99   86      345
# 2002      84   58   87   98      327
# 2003      97   48   13   97      255
# 2004      90   60  100   50      300
# col_sum  338  259  299  331     1227
5.5.3 修改数据

📝 代码示例

df2 = pd.DataFrame({
    '姓名': ['lisa', 'cc', 'john', 'lili'],
    '年龄': [18, 21, 20, 19],
    '语文成绩': [98, 95, 59, 75]
}, index=[5, 6, 7, 8])

# 修改单个值
df2.loc[df2['姓名'] == 'lisa', '年龄'] = 20
print(df2)

# 修改整列数据
df2['年龄'] = df2['年龄'] + 1
print(df2)

# 修改特定条件的数据
df2.loc[df2['姓名'] == 'cc', '年龄'] += 1
print(df2)

5.6 综合案例

🎯 案例:学生信息管理

df2 = pd.DataFrame({
    '姓名': ['lisa', 'cc', 'john', 'lili'],
    '年龄': [18, 21, 20, 19],
    '语文成绩': [98, 95, 59, 75]
}, index=[5, 6, 7, 8])

# 1. 新增一行:id为9,lulu,20,98
df2.loc[9] = ['lulu', 20, 98]

# 2. 新增一列:性别
df2['性别'] = ['女', '男', '男', '女', '女']

# 3. 将年龄数据整体+1
df2['年龄'] = df2['年龄'] + 1

# 4. 打印列名
print('列名:', df2.columns)

# 5. 打印形状
print('形状:', df2.shape)

# 6. 找到cc的性别
cc_gender = df2.loc[df2['姓名'] == 'cc', '性别'].values
print('cc的性别:', cc_gender)

# 7. 找到所有女生的数据
female_students = df2[df2['性别'] == '女']
print('女生数据:\n', female_students)

# 8. 找到成绩大于80的学生姓名
high_score = df2.loc[df2['语文成绩'] > 80, '姓名'].values
print('成绩>80的学生:', high_score)

# 9. 找到第三行和第四行,以及第一列第三列数据
result = df2.iloc[2:4, 0:3:2]
# 或
result = df2.loc[[7, 8], ['姓名', '语文成绩']]
print(result)

# 10. 把cc的年龄加1
df2.loc[df2['姓名'] == 'cc', '年龄'] += 1

🔗 关联知识
→ 6. DataFrame高级操作
→ 7. 数据读取与存储


6. DataFrame高级操作

6.1 head()和tail() - 快速查看数据

🔧 函数:df.head() / df.tail()

📊 参数说明

参数 类型 说明 默认值
n int 返回的行数 5

📝 代码示例

df2 = pd.DataFrame({
    '姓名': ['lisa', 'cc', 'john', 'lili'],
    '年龄': [18, 21, 20, 19],
    '语文成绩': [98, 95, 59, 75]
}, index=[5, 6, 7, 8])

# 查看前2行
print(df2.head(2))
# 输出:
#     姓名  年龄  语文成绩
# 5  lisa  18    98
# 6    cc  21    95

# 查看后2行
print(df2.tail(2))
# 输出:
#     姓名  年龄  语文成绩
# 7  john  20    59
# 8  lili  19    75

💎 最佳实践

✅ 推荐:读取大文件后先用head()查看数据结构
df = pd.read_csv('large_file.csv')
print(df.head())  # 快速了解数据格式

❌ 避免:直接打印整个DataFrame
print(df)  # 数据量大时会很慢

6.2 drop() - 删除数据

🔧 函数:df.drop()

📊 参数说明

参数 类型 说明 默认值
labels str/list 要删除的行/列标签 必填
axis int 0删除行,1删除列 0
inplace bool 是否在原数据上修改 False

📝 代码示例

df2 = pd.DataFrame({
    '姓名': ['lisa', 'cc', 'john', 'lili'],
    '年龄': [18, 21, 20, 19],
    '语文成绩': [98, 95, 59, 75]
}, index=[5, 6, 7, 8])

# 删除列(不修改原数据)
result = df2.drop(labels='姓名', axis=1)
print(result)
# 输出:
#    年龄  语文成绩
# 5  18    98
# 6  21    95
# 7  20    59
# 8  19    75

# 删除行(直接修改原数据)
df2.drop(labels=[7, 8], axis=0, inplace=True)
print(df2)
# 输出:
#     姓名  年龄  语文成绩
# 5  lisa  18    98
# 6    cc  21    95

⚠️ 注意事项

  • inplace=False(默认):返回新DataFrame,不修改原数据
  • inplace=True:直接修改原数据,返回None
  • 删除多个行/列时,labels参数传入列表

6.3 sort_values() - 按值排序

🔧 函数:df.sort_values()

📊 参数说明

参数 类型 说明 默认值
by str/list 排序依据的列名 必填
ascending bool True升序,False降序 True
inplace bool 是否在原数据上修改 False

📝 代码示例

df2 = pd.DataFrame({
    '姓名': ['lisa', 'cc', 'john', 'lili'],
    '年龄': [18, 21, 20, 19],
    '语文成绩': [98, 95, 59, 75]
}, index=[5, 6, 7, 8])

# 按语文成绩降序排序
sorted_df = df2.sort_values(by='语文成绩', ascending=False)
print(sorted_df)
# 输出:
#     姓名  年龄  语文成绩
# 5  lisa  18    98
# 6    cc  21    95
# 8  lili  19    75
# 7  john  20    59

# 按多列排序
sorted_df = df2.sort_values(by=['年龄', '语文成绩'], ascending=[True, False])

6.4 sort_index() - 按索引排序

🔧 函数:df.sort_index()

📊 参数说明

参数 类型 说明 默认值
axis int 0按行索引,1按列名 0
ascending bool True升序,False降序 True
inplace bool 是否在原数据上修改 False

📝 代码示例

df2 = pd.DataFrame({
    '姓名': ['lisa', 'cc', 'john', 'lili'],
    '年龄': [18, 21, 20, 19],
    '语文成绩': [98, 95, 59, 75]
}, index=[5, 6, 7, 8])

# 按行索引降序排序
sorted_df = df2.sort_index(axis=0, ascending=False)
print(sorted_df)
# 输出:
#     姓名  年龄  语文成绩
# 8  lili  19    75
# 7  john  20    59
# 6    cc  21    95
# 5  lisa  18    98

# 按列名排序
sorted_df = df2.sort_index(axis=1, ascending=True)

6.5 综合案例:学生成绩管理系统

🎯 案例背景

np.random.seed(123)
Score = pd.DataFrame({
    "Name": ["Nancy", "Jack", "Jim", "Lili", "Simon", "Tom", "Lilei", "Jerry"],
    "Python": np.random.randint(40, 100, 8),
    "Java": np.random.randint(40, 100, 8),
    "UI": np.random.randint(40, 100, 8),
    "Class": np.random.randint(1, 3, 8)
})

📝 任务1:班级映射

# 1. Class班级:1-A,2-B
dic_class = {1: 'A', 2: 'B'}
Score['Class'] = Score['Class'].map(dic_class)
print(Score)

📝 任务2:数据修改

# 2. Jack修改为John
Score.loc[Score['Name'] == 'Jack', 'Name'] = 'John'

# 3. Simon的Java分数修改为75
Score.loc[Score['Name'] == 'Simon', 'Java'] = 75

📝 任务3:数据分析

# 4. A班Python成绩均值
a_class_avg = Score.loc[Score['Class'] == 'A', 'Python'].mean()
print('A班Python均分:', a_class_avg)

# 5. 一共有几个班,每个班多少人
class_counts = Score['Class'].value_counts()
print('班级人数:\n', class_counts)

# 6. 得到UI大于80分的学生姓名
high_ui = Score.loc[Score['UI'] > 80, 'Name'].values
print('UI>80的学生:', high_ui)

📝 任务4:成绩处理

# 1. UI成绩全部加10分
Score['UI'] = Score['UI'] + 10

# 2. 新增四列:总分、均分、最大、最小
Score['总分'] = Score[['Python', 'Java', 'UI']].sum(axis=1)
Score['均分'] = Score[['Python', 'Java', 'UI']].mean(axis=1)
Score['最大'] = Score[['Python', 'Java', 'UI']].max(axis=1)
Score['最小'] = Score[['Python', 'Java', 'UI']].min(axis=1)

# 3. 得到3科都及格的学生信息
# 方法1:使用多个条件
passed = Score[(Score['Python'] >= 60) & (Score['Java'] >= 60) & (Score['UI'] >= 60)]

# 方法2:使用最小值
passed = Score[Score['最小'] >= 60]

# 方法3:使用all()函数(推荐)
mask = (Score.iloc[:, 1:4] > 60).all(axis=1)
passed = Score[mask]
print('三科都及格的学生:\n', passed)

# 4. Tom的Class改为A
Score.loc[Score['Name'] == 'Tom', 'Class'] = 'A'

# 5. 按照总分从大到小排序
Score = Score.sort_values(by='总分', ascending=False)
print(Score)

💡 知识点:all()函数

  • all(axis=1):对每一行进行逻辑与运算
  • 所有值都为True时,结果才为True
  • 常用于检查多个条件是否同时满足

🔗 关联知识
→ 7. 数据读取与存储
→ 4. Series其他常用方法


7. 数据读取与存储

7.1 读取CSV文件

🔧 函数:pd.read_csv()

📊 常用参数说明

参数 类型 说明 默认值
filepath_or_buffer str 文件路径 必填
encoding str 文件编码(UTF-8/GBK/GB2312) None
sep str 分隔符 ‘,’
header int 哪一行作为列名 0
names list 自定义列名 None
usecols list 只读取指定列 None
index_col int/str 指定某列为行索引 None
nrows int 读取前n行 None
skiprows int/list 跳过前n行 None

📝 代码示例:基础读取

import pandas as pd

# 基础读取
df = pd.read_csv(
    filepath_or_buffer='data/HR.csv',
    encoding='GB2312'
)
print(df.head())

💡 知识点:CSV vs Excel

特性 CSV Excel
文件类型 纯文本 二进制
分隔符 逗号 -
数据表 单个 多个sheet
体积
功能 仅数据 图表/公式/格式
加载速度
适用场景 日志/原始数据/备份 财务报表/商业分析

7.2 检测文件编码

🔧 工具:chardet库

📝 代码示例

import chardet

# 检测文件编码
with open('data/HR.csv', 'rb') as f:
    result = chardet.detect(f.read(1000))  # 读取前1000字节判断

print('文件编码:', result['encoding'])
# 输出:GB2312

⚠️ 常见编码问题

  • UTF-8:国际通用,支持所有字符
  • GBK/GB2312:中文编码,Windows中文系统常用
  • ISO-8859-1:西欧字符编码

💎 最佳实践

✅ 推荐:先检测编码再读取
import chardet
with open('file.csv', 'rb') as f:
    encoding = chardet.detect(f.read(1000))['encoding']
df = pd.read_csv('file.csv', encoding=encoding)

❌ 避免:盲目尝试不同编码
df = pd.read_csv('file.csv', encoding='utf-8')  # 可能报错

7.3 高级读取参数

📝 代码示例:指定列和行

# 只读取指定列
df = pd.read_csv(
    'data/HR.csv',
    encoding='GB2312',
    usecols=['员工满意度', '项目数量', '部门']
)

# 指定某列为行索引
df = pd.read_csv(
    'data/HR.csv',
    encoding='GB2312',
    index_col=0  # 第一列作为行索引
)

# 读取前100行
df = pd.read_csv(
    'data/HR.csv',
    encoding='GB2312',
    nrows=100
)

# 跳过前5行
df = pd.read_csv(
    'data/HR.csv',
    encoding='GB2312',
    skiprows=5
)

# 自定义列名
df = pd.read_csv(
    'data/HR.csv',
    encoding='GB2312',
    header=None,  # 不使用第一行作为列名
    names=['col1', 'col2', 'col3']  # 自定义列名
)

7.4 HR数据分析案例

🎯 数据字段说明

  1. 员工满意度:员工打的分数
  2. 考核评分:领导给的分数
  3. 项目数量:负责几个项目
  4. 每月在公司工作时间:平均值
  5. 司龄:在公司第几年
  6. 工作事故:0没有,1有
  7. 是否离职:0没有,1离职
  8. 五年内是否升职:0没有,1有
  9. 部门:所在部门
  10. 薪水:低/中/高

📝 分析任务

df = pd.read_csv('data/HR.csv', encoding='GB2312')

# 1. 打印数据列名
print('列名:', df.columns)

# 2. 求公司员工满意度的均值
avg_satisfaction = df['员工满意度'].mean()
print('员工满意度均值:', avg_satisfaction)

# 3. 求公司的员工离职率
turnover_rate = df['是否离职'].value_counts() / df.shape[0]
print('离职率:\n', turnover_rate)
# 或
turnover_rate = df.loc[df['是否离职'] == 1, '是否离职'].count() / df['是否离职'].count()

# 4. 都有哪些部门,每个部门多少人
dept_counts = df['部门'].value_counts()
print('各部门人数:\n', dept_counts)

# 5. 工作时长的最大值、最小值、均值
print('工作时长最大值:', df['每月在公司工作时间'].max())
print('工作时长最小值:', df['每月在公司工作时间'].min())
print('工作时长均值:', df['每月在公司工作时间'].mean())

# 6. 薪水的占比情况
salary_ratio = df['薪水'].value_counts(normalize=True)
print('薪水占比:\n', salary_ratio)

# 7. 销售部门员工项目数量的均值
sales_avg = df.loc[df['部门'] == 'sales', '项目数量'].mean()
print('销售部门项目数量均值:', sales_avg)

# 8. 每月在公司工作时间>250,得到部门和项目数量两列数据
result = df.loc[df['每月在公司工作时间'] > 250, ['部门', '项目数量']]
print(result)

7.5 保存CSV文件

🔧 函数:df.to_csv()

📊 常用参数说明

参数 类型 说明 默认值
path_or_buf str 保存路径 必填
sep str 分隔符 ‘,’
index bool 是否保存行索引 True
header bool 是否保存列名 True
columns list 保存指定列 None
encoding str 文件编码 ‘utf-8’

📝 代码示例

stu = pd.DataFrame({
    '姓名': ['张三', '李四', '王五'],
    '年龄': [18, 19, 17],
    '成绩': [80, 70, 99]
}, index=['No1', 'No3', 'No2'])

# 保存到CSV(包含行索引)
stu.to_csv(path_or_buf='data/stu.csv')

# 保存到CSV(不包含行索引)
stu.to_csv(path_or_buf='data/stu.csv', index=False)

# 保存指定列
stu.to_csv(
    path_or_buf='data/stu.csv',
    columns=['姓名', '成绩'],
    index=False
)

7.6 读取Excel文件

🔧 函数:pd.read_excel()

⚠️ 注意事项
需要先安装openpyxl库:

pip install openpyxl -i https://repo.huaweicloud.com/repository/pypi/simple/

📝 代码示例

# 读取Excel文件
df2 = pd.read_excel('data/students.xlsx')
print(df2)

# 读取指定sheet
df2 = pd.read_excel('data/students.xlsx', sheet_name='Sheet1')

# 读取多个sheet
dfs = pd.read_excel('data/students.xlsx', sheet_name=None)  # 返回字典

7.7 保存Excel文件

🔧 函数:df.to_excel()

📝 代码示例

df2 = pd.DataFrame({
    '姓名': ['张三', '李四', '王五', '赵六'],
    '年龄': [18, 19, 17, 20],
    '成绩': [80, 70, 99, 85],
    '性别': ['男', '女', '男', '男']
})

# 修改数据
df2.loc[df2['姓名'] == '张三', '年龄'] = 20
df2.loc[df2['姓名'] == '赵六', '成绩'] = 98
df2.loc[df2['姓名'] == '李四', '性别'] = '男'

# 保存到Excel
df2.to_excel(excel_writer='data/new_stu.xlsx', index=False)

# 保存到指定sheet
df2.to_excel(
    excel_writer='data/new_stu.xlsx',
    sheet_name='学生信息',
    index=False
)

🔗 关联知识
→ 8. 数据库连接
→ 5. DataFrame详解


8. 数据库连接

8.1 连接MySQL数据库

🔧 工具:pymysql库

⚠️ 注意事项
需要先安装pymysql库:

pip install pymysql

📝 代码示例:建立连接

import pymysql
import pandas as pd
import warnings
warnings.filterwarnings('ignore')

# 建立数据库连接
conn = pymysql.connect(
    host='localhost',      # 数据库IP地址
    port=3306,             # 端口号
    user='root',           # 用户名
    password='123456',     # 密码
    charset='utf8',        # 字符编码
    database='games_db'    # 数据库名
)

print('连接成功:', conn)

📊 连接参数说明

参数 说明 示例
host 数据库服务器地址 ‘localhost’ / ‘192.168.1.100’
port 端口号 3306(MySQL默认)
user 用户名 ‘root’
password 密码 ‘123456’
charset 字符编码 ‘utf8’ / ‘utf8mb4’
database 数据库名 ‘test_db’

8.2 读取数据库数据

🔧 函数:pd.read_sql()

📊 参数说明

参数 类型 说明
sql str SQL查询语句
con connection 数据库连接对象
index_col str 指定某列为行索引
parse_dates list 解析为日期的列

📝 代码示例

# 读取整张表
df = pd.read_sql('SELECT * FROM sanguo', conn)
print(df)

# 条件查询
df = pd.read_sql('SELECT name, country FROM sanguo WHERE country="蜀国"', conn)
print(df)

# 聚合查询
df = pd.read_sql('SELECT country, COUNT(*) as count FROM sanguo GROUP BY country', conn)
print(df)

# 关闭连接
conn.close()

💡 知识点:SQL基础语句

-- 查询所有数据
SELECT * FROM table_name;

-- 条件查询
SELECT column1, column2 FROM table_name WHERE condition;

-- 排序
SELECT * FROM table_name ORDER BY column_name DESC;

-- 分组统计
SELECT column_name, COUNT(*) FROM table_name GROUP BY column_name;

-- 限制返回行数
SELECT * FROM table_name LIMIT 10;

8.3 完整工作流程

📝 代码示例:完整流程

import pymysql
import pandas as pd

# 1. 建立连接
conn = pymysql.connect(
    host='localhost',
    port=3306,
    user='root',
    password='123456',
    charset='utf8',
    database='games_db'
)

# 2. 读取数据
df = pd.read_sql('SELECT * FROM sanguo', conn)

# 3. 数据分析
print('数据形状:', df.shape)
print('前5行:\n', df.head())
print('数据类型:\n', df.dtypes)

# 4. 数据处理
# ... 进行各种数据分析和处理 ...

# 5. 关闭连接
conn.close()

⚠️ 注意事项

  • 使用完数据库后要记得关闭连接
  • 敏感信息(密码)不要硬编码在代码中
  • 大数据量查询时注意内存占用
  • 使用参数化查询防止SQL注入

💎 最佳实践

✅ 推荐:使用上下文管理器自动关闭连接
with pymysql.connect(...) as conn:
    df = pd.read_sql('SELECT * FROM table', conn)
# 连接自动关闭

❌ 避免:忘记关闭连接
conn = pymysql.connect(...)
df = pd.read_sql('SELECT * FROM table', conn)
# 忘记conn.close(),可能导致连接泄漏

📚 知识点速查表

📊 核心知识点思维导图

Pandas数据分析
├── 1. 核心数据结构 ⭐
│   ├── Series(一维)
│   │   ├── 创建:pd.Series(data, index, dtype, name)
│   │   ├── 属性:index, values, dtype, shape, size, ndim
│   │   ├── 访问:位置索引[0]、标签索引['label']
│   │   └── 统计:mean(), sum(), max(), min(), std()
│   │
│   └── DataFrame(二维)
│       ├── 创建:pd.DataFrame(data, index, columns)
│       ├── 属性:index, columns, values, shape, dtypes, ndim, size
│       ├── 查询:df['col'], df.loc[], df.iloc[], df[condition]
│       └── 修改:df['col']=value, df.loc[]=value
│
├── 2. Series字符串操作 ⭐⭐
│   ├── 基础方法
│   │   ├── str.strip() - 去除首尾字符
│   │   ├── str.split() - 字符串分割
│   │   ├── str.replace() - 字符串替换
│   │   └── str[0:3] - 字符串切片
│   │
│   └── 高级方法
│       ├── str.contains() - 包含检查(支持正则)
│       ├── str.count() - 统计出现次数
│       ├── str.len() - 计算字符串长度
│       └── str.find() - 查找子串位置
│
├── 3. Series数据处理 ⭐⭐
│   ├── 成员检查
│   │   ├── isin() - 检查是否在列表中
│   │   └── 布尔索引 - series[condition]
│   │
│   ├── 去重统计
│   │   ├── unique() - 返回唯一值数组
│   │   ├── nunique() - 返回唯一值数量
│   │   └── value_counts() - 分类计数(支持normalize)
│   │
│   └── 数据转换
│       ├── map() - 映射转换(字典/函数)
│       └── shift() - 数据偏移(计算环比)
│
├── 4. DataFrame查询 ⭐⭐⭐
│   ├── 列查询
│   │   ├── df['col'] - 单列(返回Series)
│   │   ├── df[['col1','col2']] - 多列(返回DataFrame)
│   │   └── df.col - 属性访问(仅合法标识符)
│   │
│   ├── 行查询
│   │   ├── df[0:2] - 切片查询
│   │   ├── df.iloc[0:2, 0:2] - 位置索引(前闭后开)
│   │   └── df.loc['a':'b', 'col1':'col2'] - 标签索引(前闭后闭)
│   │
│   └── 条件查询
│       ├── df[df['col'] > 60] - 单条件
│       ├── df[(df['col1']>60) & (df['col2']<90)] - 多条件
│       └── df.loc[condition, ['col1','col2']] - 指定列
│
├── 5. DataFrame修改 ⭐⭐⭐
│   ├── 新增数据
│   │   ├── df['new_col'] = values - 新增列
│   │   ├── df.loc['new_row'] = values - 新增行
│   │   └── df['sum'] = df.sum(axis=1) - 计算列
│   │
│   ├── 修改数据
│   │   ├── df['col'] = df['col'] + 1 - 整列修改
│   │   ├── df.loc[condition, 'col'] = value - 条件修改
│   │   └── df.loc[index, 'col'] = value - 单值修改
│   │
│   └── 删除数据
│       ├── df.drop(labels, axis=0) - 删除行
│       ├── df.drop(labels, axis=1) - 删除列
│       └── inplace=True - 直接修改原数据
│
├── 6. DataFrame高级操作 ⭐⭐
│   ├── 查看数据
│   │   ├── df.head(n) - 查看前n行
│   │   ├── df.tail(n) - 查看后n行
│   │   └── df.info() - 查看数据信息
│   │
│   ├── 排序操作
│   │   ├── df.sort_values(by='col') - 按值排序
│   │   ├── df.sort_index() - 按索引排序
│   │   └── ascending=False - 降序排列
│   │
│   └── 统计分析
│       ├── df.describe() - 描述性统计
│       ├── df.sum(axis=0/1) - 求和(按列/行)
│       ├── df.mean(axis=0/1) - 平均值
│       └── df.max()/min() - 最大/最小值
│
├── 7. 数据读取与存储 ⭐⭐⭐
│   ├── CSV文件
│   │   ├── pd.read_csv(path, encoding, sep, header)
│   │   ├── df.to_csv(path, index, encoding)
│   │   └── 编码检测:chardet.detect()
│   │
│   ├── Excel文件
│   │   ├── pd.read_excel(path, sheet_name)
│   │   ├── df.to_excel(path, sheet_name, index)
│   │   └── 需要:pip install openpyxl
│   │
│   └── 高级参数
│       ├── usecols - 指定读取列
│       ├── nrows - 读取前n行
│       ├── skiprows - 跳过前n行
│       └── index_col - 指定索引列
│
└── 8. 数据库连接 ⭐⭐
    ├── MySQL连接
    │   ├── pymysql.connect() - 建立连接
    │   ├── pd.read_sql(sql, conn) - 读取数据
    │   └── conn.close() - 关闭连接
    │
    └── SQL查询
        ├── SELECT * FROM table - 查询所有
        ├── WHERE condition - 条件筛选
        ├── ORDER BY col DESC - 排序
        └── GROUP BY col - 分组统计

📋 函数速查表

Series创建与属性
函数/属性 语法 说明 优先级
pd.Series() pd.Series(data, index, dtype, name) 创建Series
ndim s.ndim 维度(固定为1)
shape s.shape 形状(元素个数,)
size s.size 元素总数
dtype s.dtype 数据类型
index s.index 行索引对象
values s.values 值(NumPy数组)
Series字符串方法
方法 语法 说明 优先级
str.strip() s.str.strip('chars') 去除首尾指定字符 ⭐⭐
str.split() s.str.split('-', expand=True) 字符串分割(expand展开为DataFrame) ⭐⭐⭐
str.replace() s.str.replace('old', 'new') 字符串替换 ⭐⭐⭐
str.contains() s.str.contains('pattern', case=False) 包含检查(支持正则) ⭐⭐⭐
str.count() s.str.count('substring') 统计子串出现次数 ⭐⭐
str.len() s.str.len() 计算字符串长度 ⭐⭐
str.find() s.str.find('substring') 查找子串位置(-1表示未找到)
str[start:end] s.str[0:3] 字符串切片 ⭐⭐
Series数据处理方法
方法 语法 说明 优先级
isin() s.isin(['value1', 'value2']) 成员检查 ⭐⭐⭐
unique() s.unique() 返回唯一值数组 ⭐⭐⭐
nunique() s.nunique() 返回唯一值数量 ⭐⭐
value_counts() s.value_counts(normalize=True) 分类计数(normalize返回占比) ⭐⭐⭐
map() s.map({1:'A', 2:'B'}) 映射转换(字典或函数) ⭐⭐⭐
shift() s.shift(1) 数据偏移(正数向下,负数向上) ⭐⭐
Series统计方法
方法 语法 说明 优先级
sum() s.sum() 求和
mean() s.mean() 平均值
std() s.std(ddof=1) 标准差(ddof=1为样本标准差)
min() s.min() 最小值
max() s.max() 最大值
DataFrame创建与属性
函数/属性 语法 说明 优先级
pd.DataFrame() pd.DataFrame(data, index, columns) 创建DataFrame
shape df.shape 形状(行数, 列数)
ndim df.ndim 维度(固定为2)
size df.size 元素总数
dtypes df.dtypes 每列的数据类型
index df.index 行索引对象
columns df.columns 列名对象
values df.values 值(NumPy数组)
DataFrame查询方法
方法 语法 说明 优先级
列查询 df['col']df[['col1','col2']] 单列返回Series,多列返回DataFrame ⭐⭐⭐
行切片 df[0:2] 按位置切片查询行 ⭐⭐
iloc df.iloc[0:2, 0:2] 位置索引(前闭后开) ⭐⭐⭐
loc df.loc['a':'b', 'col1':'col2'] 标签索引(前闭后闭) ⭐⭐⭐
条件查询 df[df['col'] > 60] 布尔索引筛选 ⭐⭐⭐
head() df.head(n) 查看前n行(默认5) ⭐⭐⭐
tail() df.tail(n) 查看后n行(默认5) ⭐⭐⭐
DataFrame修改方法
方法 语法 说明 优先级
新增列 df['new_col'] = values 添加新列 ⭐⭐⭐
新增行 df.loc['new_row'] = values 添加新行 ⭐⭐⭐
修改数据 df.loc[condition, 'col'] = value 条件修改 ⭐⭐⭐
drop() df.drop(labels, axis=0/1, inplace=True) 删除行/列 ⭐⭐
DataFrame排序方法
方法 语法 说明 优先级
sort_values() df.sort_values(by='col', ascending=False) 按值排序 ⭐⭐⭐
sort_index() df.sort_index(axis=0, ascending=True) 按索引排序 ⭐⭐
DataFrame统计方法
方法 语法 说明 支持axis 优先级
sum() df.sum(axis=0/1) 求和
mean() df.mean(axis=0/1) 平均值
std() df.std(axis=0/1) 标准差 ⭐⭐
min() df.min(axis=0/1) 最小值
max() df.max(axis=0/1) 最大值
describe() df.describe() 描述性统计 ⭐⭐
数据读取函数
函数 语法 常用参数 优先级
pd.read_csv() pd.read_csv(path, encoding, sep, header, usecols, nrows) encoding, usecols, nrows ⭐⭐⭐
pd.read_excel() pd.read_excel(path, sheet_name) sheet_name ⭐⭐⭐
pd.read_sql() pd.read_sql(sql, conn) sql, conn ⭐⭐
数据存储函数
函数 语法 常用参数 优先级
df.to_csv() df.to_csv(path, index=False, encoding='utf-8') index, encoding ⭐⭐⭐
df.to_excel() df.to_excel(path, sheet_name, index=False) sheet_name, index ⭐⭐⭐
df.to_sql() df.to_sql(table_name, conn) table_name, conn ⭐⭐

⚠️ 常见错误与解决方案

错误类型 错误示例 正确写法 说明
字符串方法 s.strip() s.str.strip() 必须使用.str访问器
多列查询 df['col1', 'col2'] df[['col1', 'col2']] 多列需要双层方括号
逻辑运算 df[df['a']>60 and df['b']<90] df[(df['a']>60) & (df['b']<90)] 使用&且加括号
loc vs iloc df.loc[0:2, 0:2] df.iloc[0:2, 0:2] loc用标签,iloc用位置
链式索引 df[df['a']>60]['b'] df.loc[df['a']>60, 'b'] 避免链式索引警告
inplace参数 df = df.drop('col', axis=1) df.drop('col', axis=1, inplace=True) 理解inplace含义

📖 参考资源

  • 官方文档:https://pandas.pydata.org/docs/
  • 中文教程:https://www.pypandas.cn/
  • 在线练习:https://www.kaggle.com/learn/pandas
  • 视频教程:https://www.bilibili.com/(搜索Pandas教程)

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐