【Python数据分析】pandas apply自定义函数+分组操作+分析案例

文章目录

  • 1.apply()
    • 1.1函数 操作series对象
    • 1.2 apply()函数 => 操作DataFrame对象
    • 1.3 向量化函数
    • 1.4 apply()函数的案例-泰坦尼克号数据集
    • 1.5 apply()函数 结合 lambda表达式使用.
  • 2. 分组操作
    • 2.1 分组 + 聚合操作
    • 2.2 分组 + 转换
    • 2.3 分组 + 过滤
    • 2.4 DataFrameGroupby df的分组对象
  • 3. 分析案例

1.apply()

1.1函数 操作series对象

apply()函数操作Series对象, 是把Series的逐个值进行传入并操作的.

语法 : df对象.apply(函数对象,参数名(如果有) 参数1 …)

df = pd.DataFrame({'a': [10, 20, 30], 'b': [20, 30, 40]})
def my_fun1(x):print('看看我执行了嘛!')return x ** 2# 扩展: 定义函数, 计算x的e次方.
def my_fun2(x, e):return x ** e
df['a'].apply(my_fun1)  # 细节: 这里写的是函数名, 即: 函数对象.  如果写: 函数名() 则表示是在调用函数.df.a.apply(my_fun2, e=3)  # 细节: 传参数时, 使用 关键字参数 写法进行传参.

1.2 apply()函数 => 操作DataFrame对象

DataFrame 的 apply() 默认是传入整列的 而不是 逐个值进行传入的

语法 df对象.apply(函数对象,参数名(如果有) 参数1 …)

# df 的 apply() 默认是传入整列的 而不是 逐个值进行传入的
def my_fun3(col):x = col[0]y = col[1]z = col[2]print(col)print(type(col))return (x + y + z)/3def my_fun4(col):return col.mean()
df.apply(my_fun3)
df.apply(my_fun4)

在这里插入图片描述

1.3 向量化函数

当 函数 传入的 是 向量 即 需要手动遍历输出的时候 可以使用 np.vectorize 装饰器自动遍历

@np.vectorize
def my_fun6(x, y):# 判断, 如果x的值是20, 就返回NaNif x == 20:         # 报错: x是向量, 20是标量, 向量和标量无法直接计算. return np.NAN# for i in x:#     if i == 20:         # 手动遍历, 就不报错了, 但是结果不是我们要的.#         return np.NAN# x代表第1列数据, y代表第2列数据return (x + y) / 2# 调用函数
my_fun6(df.a, df.b)
# 传统写法.
my_fun6 = np.vectorize(my_fun6)     # 装饰后的函数对象 = 装饰器(要被装饰的函数名)
my_fun6(df.a, df.b)

1.4 apply()函数的案例-泰坦尼克号数据集

  • 需求1: 计算泰坦尼克号数据中, 每列的null值总数, 缺失占比, 非缺失值占比.
# 1. 加载数据集, 获取df对象.
train = pd.read_csv('data/titanic_train.csv')
# 1. 定义函数 count_missing(), 计算每列的缺失值总数
def count_missing(col):           # col => 每列数据, Series对象return col.isnull().sum()# 2. 定义函数 prop_missing(), 计算每列的缺失值占比.
def prop_missing(col):# 缺失值占比 = 缺失值数量 / 该列总长度# return count_missing(col) / len(col)return count_missing(col) / col.size# 3. 定义函数 prop_not_missing(), 计算每列的非缺失值占比.
def prop_not_missing(col):# 非缺失值占比 = 1 - 缺失值占比return 1 - prop_missing(col)# 4. 调用上述的函数, 获取结果.
train.apply(count_missing)      # 获取每列的缺失值总数
train.apply(prop_missing)       # 获取每列的缺失值占比 
train.apply(prop_not_missing)   # 获取每列的非缺失值占比 

在这里插入图片描述

  • 需求2: 计算泰坦尼克号数据中, 各年龄段总人数.
# 方式1: 直接算每个年龄出现了多少次, 即: 每个年龄的总人数, 但是达不到我们要的效果.
train.Age.value_counts()
# 解题思路: 把年龄变成年龄段的值, 然后再进行统计.
# 1. 定义函数, 接收年龄, 将其转成年龄段. 
def cut_age(age):if 0 <= age < 18:return '未成年'elif 18 <= age < 40:return '青年'elif 40 <= age < 60:return '壮年'elif 60 <= age < 80:return '老年'else:return '未知'# 2. 把上述的函数, 作用于Age列, 得到新的列, 计算结果即可.
train.Age.apply(cut_age)
train.Age.apply(cut_age).value_counts()

在这里插入图片描述

  • 需求3: 统计VIP 和 非VIP的客户总数
# 1. 定义函数, 用于判断是否是VIP用户.
def is_vip(row):if row.Pclass == 1 and ('Master' in row.Name or 'Dr' in row.Name or 'Sir' in row.Name):return 'VIP'else:return '非VIP'train.apply(is_vip, axis=1)     # 传入整行数据
train.apply(is_vip, axis=1).value_counts()

在这里插入图片描述

1.5 apply()函数 结合 lambda表达式使用.

# 细节: 如果需求比较简单, 没有必要重新定义1个新的函数, 可以直接传入Lambda表达式.
# 1. 定义数据集.
df = pd.DataFrame({'a': [10, 20, 30], 'b': [20, 30, 40]})
# 2. 需求: 每个值 => 该值的平方.
def my_fun1(x):return x ** 2df.apply(my_fun1)
# 3. 上述的需求可以用 Lambda表达式来完成.
df.apply(lambda x : x ** 2)
df.apply(lambda x : x.mean())
df.apply(lambda x : x.mean(), axis=0)   # 效果同上.df.apply(lambda x : x.mean(), axis=1)   # 统计每行的平均值

2. 分组操作

2.1 分组 + 聚合操作

# 1. 读取数据, 获取df对象
df = pd.read_csv('data/gapminder.tsv', sep='\t')
df.head()

在这里插入图片描述

  • 语法 df对象.groupby(‘要分组的字段’)[‘要操作的字段’].聚合函数()
# 写法1
df.groupby('year')['lifeExp'].mean()
# 写法2
df.groupby('year').lifeExp.mean()# 上述都是一步到位, 直接计算结果, 我们也可以手动计算. 
# 1. 我们先看看一共有多少个年
df.year.unique()  # 12个年份, 底层算 12 次即可, 这里我们就用 1952年举例.# 2. 获取1952年所有的数据, 计算平均寿命
df[df['year'] == 1952].lifeExp.mean()
df[df.year == 1952].lifeExp.mean()  # 效果同上.
# 计算各个大洲平均寿命.
# 写法1
df.groupby('continent')['lifeExp'].mean()# 分组之后, 也可以用 describe()同时计算多个统计量.
df.groupby('continent')['lifeExp'].describe()df.groupby('continent')['lifeExp'].mean()
df.groupby('continent')['lifeExp'].agg('mean')  # 这里的mean是: pandas的函数
# df.groupby('continent')['lifeExp'].agg(np.mean)  # 这里的mean是: Numpy的函数df.groupby('continent')['lifeExp'].aggregate('mean')  # 效果同上.
# 需求3: 上述的写法, 也可以改造成 agg() 或者 aggregate()函数, 效果一致
# 计算各个大洲平均寿命.
df.groupby('continent')['lifeExp'].mean()
df.groupby('continent')['lifeExp'].agg('mean')  # 这里的mean是: pandas的函数
# df.groupby('continent')['lifeExp'].agg(np.mean)  # 这里的mean是: Numpy的函数df.groupby('continent')['lifeExp'].aggregate('mean')  # 效果同上.
#需求4: 给 agg()或者 aggregate传入字典
# 需求: 统计各个大洲 平均寿命, 人口的中位数, 最大GDP
df.groupby('continent').agg({'lifeExp': 'mean', 'pop': 'median', 'gdpPercap': 'max'})
df.groupby('continent').aggregate({'lifeExp': 'mean', 'pop': 'median', 'gdpPercap': 'max'})  # 效果同上# 语法糖, 如果聚合函数一样, 则可以简写成如下操作, 例如: 各个大洲平均寿命, 平均人口, 平均GDP
df.groupby('continent').agg({'lifeExp': 'mean', 'pop': 'mean', 'gdpPercap': 'mean'})
df.groupby('continent')[['lifeExp', 'pop', 'gdpPercap']].mean()

2.2 分组 + 转换

需求1: 计算x的 z-score分数, 也叫: 标准分数,  公式为: (x - x_mean) / x_std
# 2. 定义函数, 计算某列的 z-score分数.
def my_zscore(col):return (col - col.mean()) / col.std()  # (列值 - 平均值) / 标准差
# 3. 调用上述的格式.
df.groupby('year').lifeExp.apply(my_zscore)  # 1704条
# 4. 查看原始df的数据集总数.
df  # 结论: 分组 + 转换处理后, 数据集总数不变.
# 需求: 读取文件(小票信息), 获取df对象. 其中有1列 total_bill 表示总消费. 随机抽取4个缺失值, 然后进行填充. 
# 填充方式: 每个组的平均值. 即: 如果是Male => 就用 Male列的平均值填充, 如果是Female => Female列的平均值填充.
# 1. 读取文件, 获取DataFrame对象
df = pd.read_csv('data/tips.csv')
df# 2. 抽样方式, 从上述的df对象中, 随机抽取10条数据. 
# tips_10 = df.sample(10)     # 这里的10表示随机抽取 10 条数据.
# random_state: 随机种子, 只要种子一样, 每次抽取的数值都是一样的. 
tips_10 = df.sample(10, random_state=21)
tips_10# 3. 随机的从上述的10条数据中, 抽取4行数据, 设置他们的 total_bill(消费总金额) 为 NaN
# 写法1: 每次固定 这四条数据 的 total_bill为 空值.
# tips_10.loc[[173, 240, 243, 175], 'total_bill'] = np.NaN# 写法2: 每次随机4条数据, 设置它们的 total_bill为 空值.
# np.random.permutation()解释: 随机打乱索引值, 并返回打乱后的索引值.
tips_10.loc[np.random.permutation(tips_10.index)[:4], 'total_bill'] = np.NaN
tips_10
# 4. 分别计算 Male 和 Female 的平均消费金额, 用于填充对应组的 缺失值.
# 思路1: 直接用 整体的 总消费金额的 平均值 填充.
tips_10.fillna(tips_10.total_bill.mean())# 思路2: 自定义函数, 计算每组的平均消费金额, 进行填充
def my_mean(col):# return col.sum() / col.size     # 某列总金额 / 某列元素个数,  这种写法会导致: 本组所有的数据都会被新值覆盖.return col.fillna(col.mean())     # 用该列的平均值, 来填充该列的缺失值, 其它不变.# 调用上述函数, 实现: 分组填充, 即: 给我N条, 处理后, 还是返回N条数据.
# tips_10.groupby('sex').total_bill.apply(my_mean)      # n => 1  聚合的效果.
tips_10.groupby('sex').total_bill.transform(my_mean)    # n => n  类似于: MySQL的窗口函数的效果.# df.groupby('sex').total_bill.transform(my_mean)    # n => n  类似于: MySQL的窗口函数的效果.

2.3 分组 + 过滤

# 1. 查看源数据
df
#%%
# 2. 查看用餐人数情况.
tmp_df = df.groupby('size', as_index=False).total_bill.count()
tmp_df.columns = ['size', 'count']
tmp_dfdf.size     # 这样写, 会把 size当做 属性, 而不是 size列.
df['size'].value_counts()
#%%
# 3. 我们发现, 在所有的 消费记录中, 就餐人数 在 1, 5, 6个人的消费次数相对较少, 我们可以过滤掉这部分的数据
tmp_df = df.groupby('size').filter(lambda x : x['size'].count() > 30)
tmp_df
#%%
# 4. 验证上述筛选后的数据, size列只有 2, 3, 4 这三种就餐人数的情况.
tmp_df['size'].value_counts()
#%%
# 5. 上述代码的合并版, 一行搞定.
df.groupby('size').filter(lambda x : x['size'].count() > 30)['size'].value_counts()# 另外一种筛选的方式, 可以基于: query()函数 + 筛选条件, 找出要的合法的数据. 
df.query('size == 2 or size == 3 or size == 4')
df.query('size in [2, 3, 4]')

2.4 DataFrameGroupby df的分组对象

# 1. 从小费数据中, 随机的获取10条数据.
tips_10 = pd.read_csv('data/tips.csv').sample(10, random_state=21)
tips_10
#%%
# 2. 演示 根据性别分组, 获取: 分组对象.
grouped = tips_10.groupby('sex')      # DataFrameGroupBy 对象
grouped
#%%
# 3. 遍历上述的分组对象, 看看每个分组都是啥(即: 每个分组的数据)
for sex_group in grouped:print(sex_group)        # sex_group: 就是具体的每个分组的数据. 
#%%
# 4. 获取指定的某个分组的数据.
grouped.get_group('Male')
grouped.get_group('Female')
#%%
# 5. 需求: 使用groupby() 按 性别 和 用餐时间分组, 计算小费数据的平均值. 
df.groupby(['sex', 'time']).tip.mean()
#%%
# 6. 分组对象不能使用 0 索引获取数据
grouped
# grouped[0]      # 分组对象不能使用 0 索引获取数据, 要获取数据, 可以通过  grouped.get_group() 函数实现
grouped.get_group(('Male'))

3. 分析案例

# 1. 加载数据, 获取df对象.
customer_info = pd.read_excel('data/会员信息查询.xlsx')
customer_info.head(100)
#%% md
- 需求1: 按月统计注册的会员数量,: 计算 月增量 = 每月新增的会员数
#%%
# 思路1: groupby() + 聚合函数实现. 
# 1. 给原始的df对象, 新增1列, 表示 注册年月. 
# customer_info['注册年月'] =  customer_info['注册时间'].apply(lambda x : x.strftime('%Y-%m')) # %Y: 年,  %m: 月
customer_info.loc[:, '注册年月'] =  customer_info['注册时间'].apply(lambda x : x.strftime('%Y-%m')) # %Y: 年,  %m: 月
customer_info
#%%
# 2. 从原始的df对象中, 获取我们要的字段查看即可.
customer_info[['会员卡号', '会员等级', '会员来源', '注册时间', '注册年月']].head(10)
#%%
# 3. 计算 月增量 = 每个月新增的会员数.
month_count = customer_info.groupby('注册年月')[['会员卡号']].count()
month_count.columns = ['月增量']
month_countcustomer_info.注册年月.value_counts().sort_index()       # 效果同上.
#%%
# 思路2: pivot_table() 透视表的方式实现. 
# 参1: index, 索引列, 等价于: groupby()的分组字段.
# 参2: columns, 列索引, 要写的也是 原表中的 列名. 
# 参3: values, 统计字段, 等价于: groupby()的聚合字段.
# 参4: aggfunc, 聚合函数, 默认为: mean
customer_info.pivot_table(index='注册年月', values='会员卡号', aggfunc='count')
#%% md
- 需求2: 按月统计 月存量.  月存量 = 月增量 + 上月存量
#%%
# 1. 计算月存量
month_count['存量'] = month_count['月增量'].cumsum()
# 2. 打印结果.
month_count
#%%
# 3. 可视化数据. 
# 3.1 绘制 月增量, figsize=宽高, color=颜色, secondary_y: 启用双Y轴, legend: 图例, grid: 网格, xlabel=X轴标签, ylabel=Y轴标签
month_count.月增量.plot(figsize=(20, 10), color='green', secondary_y=True, legend=True)# 3.2 绘制 月存量
month_count.存量.plot(kind='bar', figsize=(20, 10), color='pink', xlabel='年月', ylabel='会员数量', legend=True, grid=True)#.3 绘制 标题.
plt.title('月增量/存量结果分析', fontsize=21)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/148523.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Java面试题大全(全网最全,持续更新)中级(2)

1. 集合与泛型 1.1. 什么是泛型&#xff1f;泛型的优势是什么&#xff1f; 泛型允许类、接口和方法在定义时不指定具体的类型&#xff0c;在使用时再指定类型。优势&#xff1a; 提高代码复用性。提供类型安全&#xff0c;避免强制类型转换带来的 ClassCastException。 pub…

word批量裁剪图片,并调整图片大小,不锁定纵横比

在word中有若干图片待处理&#xff0c;裁剪出指定内容&#xff0c;调整成指定大小。如下是待处理的图片&#xff1a; 这时&#xff0c;选择视图&#xff0c;选择宏&#xff0c;查看宏 选择创建宏 添加cut_picture代码如下&#xff0c;其中上、下、左、右裁剪的橡塑尺寸根据自己…

李飞飞创业公司World Labs:引领AI新方向的“大世界模型”

引言 随着人工智能的不断进步&#xff0c;AI领域涌现了许多新兴技术和研究方向。在这其中&#xff0c;李飞飞创办的World Labs凭借其独特的“空间智能”和“大世界模型”&#xff08;Large World Model, LWM&#xff09;理念&#xff0c;迅速成为焦点。尤其是在获得了2.3亿美元…

系统架构设计师教程 第10章 10.5 软件架构演化评估方法笔记

10.5 软件架构演化评估方法 ★★★☆☆ 10.5.1 演化过程已知的评估 目的在于通过对架构演化过程进行度量&#xff0c;比较架构内部结构上的差异以及由此导致的外部质量属性上的变化&#xff0c;对该演化过程中相关质量属性进行评估。 1.评估流程 架构演化评估的基本思路是将架…

IDEA快速查看类中有那些方法的快捷键

IDEA快速查看类中有那些方法的快捷键 1.显示类结构弹出窗口 你可以使用以下快捷键来快速查看当前类的方法和成员&#xff1a; Windows/Linux: Ctrl F12 macOS: Option F12 或 ⌥ F12 这会打开一个弹出窗口&#xff0c;显示当前类的结构&#xff0c;包括方法、字段、构造函…

派可数据:解锁数据潜力,驱动业务价值新增长

前 言 当前&#xff0c;企业数字化转型经过初始探索阶段&#xff0c;各行各业进入高速发展百花齐放的创新应用新阶段。创新应用阶段的核心是企业应用先进的数字技术和工具&#xff0c;对企业多年在全领域积累的各类数据&#xff0c;包括财务、业务、生产、设计、设备、工艺等结…

车载应用的多功能需求与公安、金融等行业的应用特点

随着科技的快速发展&#xff0c;车载应用的功能需求也日益多样化。除了基本的视频监控功能外&#xff0c;现代车载应用还需满足一系列高级功能&#xff0c;如无线网络视频监控、GPS卫星定位、车辆调度、语音报站、行驶信息记录以及多媒体娱乐广告播放等。这些功能在公安、金融等…

Vue 实战教程:从 0 到 1 手把手打造新手友好的聊天应用,附完整开源代码,快速上手前端开发!(包含发送消息、发送表情包、发送文件、下载文件、截图等功能)

b站视频演示效果&#xff1a; 效果图&#xff1a; 完整代码&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8" /><title>简单聊天功能示例</title><!-- 引入 Vue.js&#xff08;通过 …

深度优先搜索算法及其matlab程序详解

#################本文为学习《图论算法及其MATLAB实现》的学习笔记################# 深度优先搜索算法(DepthFirst Search),简记DFS算法,是图论中的首要算法,其思想方法渗透到图论中的许多算法之中,尤其是DFS算法在求生成树、割点、块和平面图嵌入算法中起着极为关键的作用。…

开源ids snort (windows版)

Snort-IPS-on-Windows-main资源-CSDN文库 GitHub - eldoktor1/Snort-IPS-on-Windows: A comprehensive guide to installing and configuring Snort IPS on Windows, ensuring robust network security 解压后安装 npcap-1.75.exe Snort_2_9_20_Installer.x64.exe 安装后cm…

MiniMind环境搭建训练推理测试

引子 写了那么多篇大模型环境搭建推理部署的blog&#xff0c;如果没记错有几篇就是因为GPU资源hold不住&#xff0c;没有无法得到最终结果的&#xff08;智谱AI GLM-4V-9B视觉大模型环境搭建&推理-CSDN博客&#xff09;。我个人一直觉得大模型发展最终还是要走向端侧&…

8591 计算next值

### 思路 1. **录入字符串**&#xff1a;读取用户输入的字符串个数 n&#xff0c;然后逐个读取每个字符串。 2. **计算NEXT值**&#xff1a;对于每个字符串&#xff0c;计算其NEXT数组。 3. **输出NEXT值**&#xff1a;输出每个字符串对应的NEXT数组。 ### 伪代码 function g…

DevExpress WPF中文教程:如何解决行焦点、选择的常见问题?

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

环境部署-环境变量

环境部署-环境变量 1、python设置查找环境变量2、linux设置设置查找环境变量 仅个人笔记使用&#xff0c;感谢点赞关注 1、python设置查找环境变量 python设置环境变量 import os os.environ["PYTHONPATH"] "/path/to/library"python获取环境变量 MYS…

AI时代最好的编程语言应该选择谁?

在AI的时代&#xff0c;编程语言的选择对就业机会和薪资水平有着至关重要的影响。C和Python被认为是两个极端的代表语言&#xff0c;分别适用于不同的技术需求和开发场景。然而&#xff0c;选择最有价值的编程语言&#xff0c;不仅要考虑其技术特性&#xff0c;还需要综合考虑行…

【数据结构】你真的了解哈希表吗?看完你会对数据结构——哈希表, 会有更深更全面的认识 (理论篇)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

实例讲解电动汽车VCU故障分类、故障码发送策略及Simulink建模方法

汽车作为一个上万零部件组成的工业品&#xff0c;从设计研发到试制调试再到路试可靠性测试再到车辆批量生产&#xff0c;要经历一个相当长的周期。在设计研发阶段&#xff0c;从设计方案与原理上尽量减少故障出现的可能&#xff0c;在试制调试阶段&#xff0c;通过全面的调试测…

车间设备巡检的意义与设备巡检系统的选择之道

在现代工业生产中&#xff0c;车间设备是企业的核心资产&#xff0c;其稳定运行直接关系到企业的生产效率、产品质量以及经济效益。而车间设备巡检作为设备管理的重要环节&#xff0c;具有不可忽视的重要性。 一、车间设备巡检的重要性 车间设备在长时间、高强度的运行过程中&…

C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究

思考这样一串代码的运行结果&#xff1a; #include <iostream> using namespace std; class Person { public:~Person() { cout << "~Person()" << endl; } }; class Student:public Person { public:~Student() { cout << "~Student(…

Linus Torvalds解释为什么Linux开发人员趋向老龄化反而是件好事

Linux 的关键人物莱纳斯-托瓦尔兹&#xff08;Linus Torvalds&#xff09;说&#xff0c;尽管长期以来一直有关于开源软件开发领域出现倦怠的报道&#xff0c;但 Linux 仍一如既往地强大–尽管他承认&#xff0c;由于其规模和范围&#xff0c;他的项目也许是一个例外。 本周一&…