查看全课大纲(第 41 / 101 节)
- 1.数据分析基本概念
- 2.学习数据分析的一般路线
- 3.数据分析的流程
- 4.数据类型
- 5.环境部署(1)
- 6.环境部署(2)
- 7.课程介绍
- 8.TXT文件操作
- 9.JSON文件操作
- 10.CSV文件操作
- 11.Excel文件操作
- 12.数据库及SQL常用语法
- 13.数据库基本操作
- 14.数据库多表连接
- 15.实战:欧洲职业足球数据库分析
- 16.爬虫简介
- 17.URL管理模块
- 18.网页下载模块
- 19.网页解析模块(1)
- 20.网页解析模块(2)
- 21.Scrapy简介
- 22.Scrapy使用步骤(1)
- 23.Scrapy使用步骤(2)
- 24.Scrapy使用步骤(3)
- 25.Scrapy使用步骤(4)
- 26.实战:获取国内城市空气质量指数数据
- 27.NumPy和SciPy介绍
- 28.多维数组
- 29.多维数组操作
- 30.NumPy的常用方法
- 31.向量化介绍
- 32.向量化及通用函数
- 33.实战:2016美国大选分析
- 34.数据结构-Series
- 35.数据结构-DataFrame
- 36.数据结构-Index
- 37.Series的索引操作
- 38.DataFrame的索引操作
- 39.索引操作总结
- 40.运算与对齐
- 41.函数应用操作(1) -- map
- 42.函数应用操作 (2) -- apply applymap
- 43.文件读写操作
- 44.排序操作
- 45.数据清洗--处理缺失数据
- 46.数据清洗--处理重复数据
- 47.数据清洗--替换数据
- 48.常用统计方法(1) -- describe quantile
- 49.常用统计方法(2) -- sum mean median count
- 50.常用统计方法(3) -- max min idxmax idxmin
- 51.常用统计方法(4) -- mad var std cumsum
- 52.实战:全球食品数据分析
- 53.层级索引
- 54.分组与聚合介绍
- 55.分组操作(1) -- GroupBy对象及常用聚合操作
- 56.分组操作(2) -- 自定义分组及聚合操作
- 57.透视表介绍
- 58.透视表操作
- 59.数据规整(1) -- 数据合并concat
- 60.数据规整(2) -- 数据连接merge
- 61.数据重构(3) -- 数据重构stack unstack
- 62.实战:互联网电影资料库分析
- 63.探索性数据分析EDA介绍
- 64.EDA的目的
- 65.EDA常用工具
- 66.Matplotlib绘图基本介绍
- 67.Matplotlib画布
- 68.散点图和柱状图的绘制
- 69.直方图的绘制
- 70.矩阵绘图
- 71.子图的使用
- 72.Matplotlib颜色、标记、线型
- 73.Matplotlib坐标刻度、标签、图例、标题
- 74.Seaborn介绍
- 75.数据集分布可视化(1) -- 单变量分布、双变量分布
- 76.数据集分布可视化(2) -- 变量关系可视化
- 77.类别数据可视化 -- 类别散布图、类别内数据分布、类别内统计图
- 78.交互式数据可视化工具Bokeh介绍
- 79.Bokeh绘制散点图、柱状图、盒子图、弦图
- 80.Bokeh绘制常用图形元素
- 81.3D绘图 -- mplot3d
- 82.3D曲线可视化
- 83.3D散点图可视化
- 84.3D柱状图可视化
- 85.Pandas绘图
- 86.实战:Lending Club借贷数据探索性分析及可视化
- 87.机器学习介绍及应用场景
- 88.机器学习建模介绍 (1) -- 分类
- 89.机器学习建模介绍 (2) -- 回归
- 90.机器学习建模介绍 (3) -- 聚类
- 91.机器学习分类
- 92.机器学习工具scikit-learn
- 93.使用scikit-learn的流程
- 94.数据集准备及划分
- 95.模型选择
- 96.数据预处理及特征工程
- 97.过拟合与欠拟合
- 98.模型调参介绍
- 99.模型调参方法
- 100.模型测试及评价
- 101.实战:通过移动设备行为数据预测性别和年龄
函数应用操作(1) -- map
约 11 分钟
函数应用操作 map
小象实战讲义 · Python数据分析实战
在数据处理中,我们经常需要对数据集中的每一个元素进行相同的操作,例如转换数据类型、计算新值或格式化字符串。如果使用传统的循环,代码会变得冗长且效率低下。本节将介绍 Pandas 中的 map 函数,它是一种高效、简洁的元素级函数应用方法,能够将指定函数映射到 Series 的每一个元素上,是向量化思维在 Pandas 中的直接体现。
💡 核心导读
- 什么是 map:理解
map作为“映射”的核心概念,它将一个函数应用于序列的每个元素。 - Python 内置 map:回顾 Python 高阶函数
map()的用法及其惰性求值特性。 - Pandas Series.map:掌握 Pandas 中
Series.map()方法的使用,这是本节的重点。 - 函数来源:了解可以传入
map的函数类型,包括 NumPy 通用函数和自定义函数(含 Lambda 表达式)。
从 Python 内置 map 说起
在深入 Pandas 的 map 之前,我们先回顾一下 Python 语言内置的 map() 函数。它是一个高阶函数,接收一个函数和一个可迭代对象(如列表),并返回一个 map 对象。这个 map 对象是一个迭代器,它“记录”了将函数应用于可迭代对象中每个元素的规则,但并不会立即执行计算,这种特性被称为“惰性求值”。
import math
# 构造一个示例列表
l = [0, 1, 2, 3, 4]
print("原始列表:", l)
# 使用 Python 内置 map 函数,将 math.sqrt(开平方根)映射到列表 l 的每个元素
result = map(math.sqrt, l)
# 注意:直接 print(result) 会输出形如 <map object at 0x...> 的内存地址,每次运行都不同,
# 因此这里打印「类型」这一确定性信息,而非对象本身
print("map对象的类型:", type(result).__name__)
print("map对象是一个惰性迭代器,此刻计算尚未发生")原始列表: [0, 1, 2, 3, 4]
map对象的类型: map
map对象是一个惰性迭代器,此刻计算尚未发生可以看到,map() 返回的对象类型是 map,它是一个迭代器——此刻计算并未发生。(如果你在自己的机器上直接 print(result),会看到形如 <map object at 0x...> 的输出,其中的内存地址每次运行都不同,这正说明它是一个尚未展开的惰性对象。)
如何触发实际计算? 我们需要通过迭代(如使用 for 循环)或将其转换为列表等操作来“消费”这个迭代器。
import math
l = [0, 1, 2, 3, 4]
result = map(math.sqrt, l)
# 通过 list() 触发计算,获取结果
calculated_result = list(result)
print("计算结果列表:", calculated_result)计算结果列表: [0.0, 1.0, 1.4142135623730951, 1.7320508075688772, 2.0]现在,我们得到了每个元素开根号后的结果。Python 内置 map 的这种机制有利于处理大规模数据时节省内存,因为不需要一次性生成所有结果。
Pandas 中的 Series.map
Pandas 为 Series 对象提供了 .map() 方法,其核心思想与 Python 内置 map 一脉相承,都是“映射”。但 Series.map() 是立即执行的,并且直接返回一个新的 Series,使用起来更加直观和方便。
重要限制:本节讲的 .map() 是 Series 的方法,作用于单列。DataFrame 逐元素映射的历史方法是 applymap,pandas 2.1 起更名为 DataFrame.map(pandas 3.0 已移除旧名 applymap),将在下一节详细讲解。本节我们专注于 Series.map。
它的基本语法是:Series.map(func),其中 func 可以是:
- NumPy 的通用函数(ufunc),如
np.sqrt。 - 一个普通的 Python 函数。
- 一个字典(用于值替换,下节会详述)。
- 另一个
Series(用于根据索引对齐映射)。
使用 NumPy 通用函数
NumPy 的通用函数是经过高度优化的,在 Pandas 中使用它们能获得最佳性能。
import pandas as pd
import numpy as np
# 创建一个 Series
s = pd.Series([0, 1, 2, 3, 4])
print("原始 Series:")
print(s)
# 使用 np.sqrt 对 Series 的每个元素开根号
s_sqrt = s.map(np.sqrt)
print("\n应用 np.sqrt 后的 Series:")
print(s_sqrt)原始 Series:
0 0
1 1
2 2
3 3
4 4
dtype: int64
应用 np.sqrt 后的 Series:
0 0.000000
1 1.000000
2 1.414214
3 1.732051
4 2.000000
dtype: float64使用自定义函数与 Lambda 表达式
当我们需要进行的操作没有现成的 NumPy 函数时,可以自定义函数。对于简单的单行逻辑,使用 lambda 匿名函数最为便捷。
示例1:使用 Lambda 表达式 假设要对每个元素进行 x² + 1 的运算。
import pandas as pd
s = pd.Series([0, 1, 2, 3, 4])
print("原始 Series:")
print(s)
# 使用 lambda 表达式定义映射函数
s_custom = s.map(lambda x: x**2 + 1)
print("\n应用 lambda x: x**2 + 1 后的 Series:")
print(s_custom)原始 Series:
0 0
1 1
2 2
3 3
4 4
dtype: int64
应用 lambda x: x**2 + 1 后的 Series:
0 1
1 2
2 5
3 10
4 17
dtype: int64示例2:使用具名函数 如果操作逻辑比较复杂,需要多行代码才能完成,则可以先定义一个具名函数,再将函数名传入 .map()。
import pandas as pd
# 定义一个复杂的函数
def complex_operation(x):
"""对输入值进行一个虚构的复杂计算"""
step1 = x ** 3 # 计算立方
step2 = step1 * 2 + 1 # 进一步计算
return step2
s = pd.Series([0, 1, 2, 3, 4])
print("原始 Series:")
print(s)
# 将自定义的复杂函数映射到 Series
s_complex = s.map(complex_operation)
print("\n应用 complex_operation 函数后的 Series:")
print(s_complex)原始 Series:
0 0
1 1
2 2
3 3
4 4
dtype: int64
应用 complex_operation 函数后的 Series:
0 1
1 3
2 17
3 55
4 129
dtype: int64map 的优势与使用场景
与显式使用 for 循环相比,map 具有显著优势:
- 代码简洁:一行代码即可完成元素级转换,意图清晰。
- 效率视函数而定:传入 NumPy ufunc(如
np.sqrt)时走 C 实现的向量化路径,远快于 Python 循环;但传入普通 Python 函数或 lambda 时,map仍是逐元素的 Python 级调用,并不比手写循环快多少——追求性能时应优先用 ufunc,或直接写np.sqrt(s)这样的向量化表达式。 - Pandas 集成:返回结果仍是
Series,索引自动对齐并保留,可直接用于后续的 Pandas 操作。
map 非常适合用于数据清洗和特征工程中的列变换,例如:
- 格式化字符串(如统一日期格式)。
- 类型转换(如将字符串数字转为数值)。
- 基于条件或公式计算新值。
📝 动手练一练
- 概念辨析:Python 内置的
map()函数和 Pandas 的Series.map()方法在返回结果和执行时机上有什么主要区别?
👉 点击查看参考答案
- 返回结果:Python 内置
map()返回一个map迭代器对象;Pandas 的Series.map()直接返回一个新的Series。 - 执行时机:Python 内置
map()是惰性求值的,只有在迭代或转换为列表等容器时才会真正执行计算;Pandas 的Series.map()是立即执行的,调用后立即返回计算结果。 - 使用场景:Python
map()用于通用的可迭代对象;PandasSeries.map()是专为 Pandas Series 设计的方法,能更好地与 Pandas 生态集成(如保留索引)。
- 动手实践:假设有一个 Series 存储了商品价格(单位:元),
prices = pd.Series([99.8, 150.0, 299.5, 45.9])。请使用map函数和lambda表达式,计算每个商品在打 8.8 折后的价格(结果保留两位小数)。提示:可以使用round(x, 2)进行四舍五入。
👉 点击查看参考答案
import pandas as pd
prices = pd.Series([99.8, 150.0, 299.5, 45.9])
discounted_prices = prices.map(lambda x: round(x * 0.88, 2))
print(discounted_prices)输出应为:
0 87.82
1 132.00
2 263.56
3 40.39
dtype: float64本章小结
本节我们深入学习了 Pandas 中强大的元素级变换工具——Series.map()。我们理解了其“映射”的本质,并通过对比 Python 内置 map() 函数,掌握了其立即执行和返回 Series 的特性。我们重点练习了如何向 map 中传入 NumPy 通用函数和自定义函数(包括简洁的 lambda 表达式),从而高效、优雅地完成数据列的整体转换。
📋 行动清单
学完本节,你可以立即:
- 在遇到需要对
Series每个元素进行相同操作的场景时,优先考虑使用.map()替代for循环。 - 练习将简单的数据转换逻辑(如单位换算、字符串处理)写成
lambda表达式,并应用于.map()。 - 了解
np.sqrt,np.log等常用 NumPy 通用函数,并在合适场景下通过.map()调用它们以提升性能。
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。
- 下载本节课件:函数应用操作(1) -- mapPDF · 229KB
- 下载全套课件打包(第1-5章)ZIP · 12.8MB
- 下载全套课件打包(第6-8章)ZIP · 15MB
- 下载实战数据集:AppleStore 应用商城分析ZIP · 329KB
- 下载实战数据集:女性服装电商分析ZIP · 2.8MB
- 下载Python 数据分析环境搭建指南PDF · 2MB
- 下载Scrapy 安装教程PDF · 12.7MB
- 下载附加实战项目:AppleStore 应用商城数据分析ZIP · 0.3MB · ipynb + CSV 数据
- 下载附加实战项目:银行电话营销数据分析ZIP · 0.4MB · ipynb + CSV 数据
- 下载附加实战项目:女性服装电商评论数据分析ZIP · 2.7MB · ipynb + CSV 数据
- 下载附加实战项目:美国化学学会杂志数据分析ZIP · 34.2MB · ipynb + SQLite 数据库