当前位置: 首页 > news >正文

数据处理与统计分析 —— apply自定义函数

目录

一、向量化与伪向量化

1、向量化

2、np.vectorize 伪向量化(特定场景)

3、apply(自定义函数)

二、apply函数

1、对series中使用apply

2、对dataframe中使用apply

3、apply函数案例-泰坦尼克号数据集]

数据集下载链接:

链接:https://pan.quark.cn/s/2598999d11dd?pwd=Xx7N
提取码:Xx7N

一、向量化与伪向量化

        在pandas中,向量化操作指的是直接在整个数组上执行操作,而不是循环遍历每个元素,这些操作底层是由高效的c代码实现的,并且利用了现代的cpu的SIMD指令(单指令多数据流),向量化操作在pandas和numpy中非常常见。

1、向量化

        (1)操作示例

import pandas as pd
df = pd.DataFrame({'A':[1,2,3], 'B':[4,5,6]]})
df['C'] = df['A'] + df['B'] # 列与列相加
df['D'] = df['A'] * 10      # 列乘以标量
df['E'] = np.log(df['A'])   # 使用numpy的log函数作用于整列

        (2)向量化特点:

                        极高性能:比循环快100-1000倍

                        简洁的语法:类似于数学公式的表达方式

                        广泛的支持:数学、统计、字符串、日期等操作

2、np.vectorize 伪向量化(特定场景)

        np.vectorize是一个将普通的python函数转换成能够处理numpy数组的函数(伪向量化函数),注意:它不是真正的向量化,底层仍然是循环遍历每个元素,只是实现了一种方便的接口。可以使我们可以像向量化函数一样去调用它。

    (1)np.vectorize 伪向量化特点:

                伪向量化:内部仍然是python循环,仅提供了向量化接口

                性能比纯循环快2-5倍左右,但是比真正的向量化慢10-100倍

                优势在于简化了代码结构

      (2)使用场景:

                场景1:当需要一个自定义标量函数应用到数组的每个元素,且该函数无法用pandas/numpy内置函数直接表示时。
                例如:我们有一个复杂的函数,包含了多个条件的分支

def my_fun(x):
if x < 0:return 0
elif 0 <= x < 1:return x ** 2
else:return 2*x - 1# 使用np.vectorize
vfunc = np.vectorize(my_fun)# 应用在series
s = pd.Series([-0.5, 0.3, 0.9, 1.5, 2.0])
result = vfunc(s) # 返回:[0, 0.09, 0.81, 2.0, 3.0]

                场景2:当函数有多个参数(其中有一些函数需要固定)时

def my_fun2(x, a, b):return a * x + b
# 需要固定a和b的值,只有x向量化
vfunc2 = np.vectorize(my_fun2, excluded=['a', 'b']))

3、apply(自定义函数)

apply()函数是pandas的方法,沿着dataFrame的轴(行或者列)应用自定义函数

        特点:
            灵活:既可以处理行又可以处理列
            性能比较低:本质上是循环操作

性能:向量化函数>伪向量化函数>apply(自定义函数)

二、apply函数

        apply函数是pandas中自由度(自定义)最高的函数之一,用来对series、dataframe或者分组对象应用自定义函数。
核心行为:
    1:对series,逐个元素进行处理(输入单个值,输出单个值)
    2:对dataframe,按照行(axis=1)或者列(axis=0)传递数据(输入整行/整列数据,输出结果)
    3:对groupby对象,处理每个分组(输入分组子集,输出聚合结果)
核心作用:替代循环,实现批量处理,代码简介高效。
特点:逐行处理

1、对series中使用apply

需求:自定义函数my_fun1(),实现接受series对象,然后将接收到的每一个元素,计算其平方结果

def my_fun1(x):return x ** 2s = pd.Series([1,2,3,4])
r1 = s.apply(my_fun1)
print(r1)

输出结果:
0     1
1     4
2     9
3    16
dtype: int64

需求:自定义函数my_fun2(),接受传入参数的函数,例如:my_fun2(x, e)

def my_fun2(x, e):return x ** er2 = s.apply(my_fun2, e=3)
print(r2)

0     1
1     8
2    27
3    64
dtype: int64

2、对dataframe中使用apply

        series的apply函数调用自定义函数,自定义函数接收到是数组中的每个元素,df接收到的是一整行或者整列

#1:创建df对象,创建两个列
df = pd.DataFrame({'a':[10,20,30], 'b': [20,30,40]})
print(df.head())# 2:创建自定义函数my_fun3(), 作用于df对象
def my_fun3(x):print(f"x的内容:\n{x}")print(f"x的类型:{type(x)}")# 直接调用上述的my_fun3(),作用于df对象
# 不需要接受返回值输出,因为这个自定义函数没有返回值
df.apply(my_fun3)   # 默认是按照列输出
df.apply(my_fun3, axis=0)   # axis值为0,就是按照列输出
df.apply(my_fun3, axis=1)   # axis值为1,就是按照行输出

3、apply函数案例-泰坦尼克号数据集

import pandas as pd
df = pd.read_csv("data/titanic_train.csv")# 需求1:自定义函数,分别计算泰坦尼克号数据集某列的缺失值的个数,某列的缺失值占比,某列的非缺失值占比
# pd.isnull
def count_missing(vec):# vec就是接受到dfs对象的某列或者某行数据(要么是一整行数据要么是一整列数据)return pd.isnull(vec).sum() # 对传入的一整行或者一整列,计算缺失值的数量# 某列的缺失值占比
def prop_missing(vec):# 缺失值的占比公式:某列的缺失值数量/某列的元素的总个数return pd.isnull(vec).sum() / vec.size# 某列的非缺失值占比
def prop_complete(vec):return 1-prop_missing(vec)# 测试上面的函数
# 默认:axis=0, 即:以列的方式传入的
print(f"以列的形式传入,计算某列的缺失值个数:\n{df.apply(count_missing)}") # 计算的是所有的列,没有指定某个列,所有列中缺失值的数量
print(f"以列的形式传入,计算某列的缺失值占比:\n{df.apply(prop_missing)}")
print(f"以列的形式传入,计算某列的非缺失值占比:\n{df.apply(prop_complete)}")# 默认:axis=1, 即:以行的方式传入的
print(f"以行的形式传入,计算某行的缺失值个数:\n{df.apply(count_missing, axis=1)}") # 计算的是所有的列,没有指定某个列,所有列中缺失值的数量
print(f"以行的形式传入,计算某列的缺失值占比:\n{df.apply(prop_missing, axis=1)}")
print(f"以行的形式传入,计算某列的非缺失值占比:\n{df.apply(prop_complete, axis=1)}")

计算某列的缺失值个数:PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64

计算某列的缺失值占比:PassengerId    0.000000
Survived       0.000000
Pclass         0.000000
Name           0.000000
Sex            0.000000
Age            0.198653
SibSp          0.000000
Parch          0.000000
Ticket         0.000000
Fare           0.000000
Cabin          0.771044

Embarked       0.002245
dtype: float64
计算某列的非缺失值占比:PassengerId    1.000000
Survived       1.000000
Pclass         1.000000
Name           1.000000
Sex            1.000000
Age            0.801347
SibSp          1.000000
Parch          1.000000
Ticket         1.000000
Fare           1.000000
Cabin          0.228956
Embarked       0.997755
dtype: float64

http://www.dtcms.com/a/343648.html

相关文章:

  • lesson44:Redis 数据库全解析:从数据类型到高级应用
  • 鸿蒙开发中的List组件详解
  • spring之自定义拦截器:HandlerInterceptor 控制请求生死权
  • Java微服务开发:从入门到精通
  • 证书只是手段:把学习变成可复用能力的路线图
  • FPGA 在情绪识别领域的护理应用(三)
  • gRPC 与 HTTP 性能对比分析
  • C++浅拷贝和深拷贝区别
  • 【华为OD-C卷-019 对称字符串 100分(python、java、c++、js、c)】
  • 【Transient-Free 3DGS】delayed densification + coarse to fine增加GS的鲁棒性
  • 【GaussDB】使用gdb定位GaussDB编译package报错
  • 图像中物体计数:基于YOLOv5的目标检测与分割技术
  • 智能编程中的智能体与 AI 应用:概念、架构与实践场景
  • Effective C++ 条款54:熟悉标准库
  • typescript常用命令选项
  • Function Call与MCP:大模型能力扩展的两条路径对比
  • CF每日4题(1500-1700)
  • 谈谈架构的内容
  • 前端别名与环境变量使用
  • AI 赋能教育变革:机遇、实践与展望
  • 基于随机森林的红酒分类与特征重要性分析
  • MySQL高可用之MHA实战
  • 【高等数学】第九章 多元函数微分法及其应用——第九节 二元函数的泰勒公式
  • 北京JAVA基础面试30天打卡14
  • 【51单片机学习】AT24C02(I2C)、DS18B20(单总线)、LCD1602(液晶显示屏)
  • AI 在医疗领域的应用与挑战
  • 带宽评估(三)lossbase_v2
  • 测试面试题第二篇:专项业务领域(上)
  • 嵌入式学习day33-网络-c/s
  • 有符号和无符号的区别