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

python利用pandas统计分析—groupby()函数的使用

文章目录

  • 一、groupby使用场景
  • 二、groupby基本原理
  • 三、groupby分组运算
    • 基础聚合操作:只能选择一种聚合操作
    • agg 聚合操作:可以针对同列选择不同聚合方法
    • transform
    • apply
  • 四、groupby分组后去重统计nunique()
  • 五、groupby分组后重命名列名
    • rename()
    • 直接重新命名列名
    • 重命名所有的列名:add_prefix() /add_suffix()


一、groupby使用场景

在日常数据分析中,经常需要将数据根据某个(多个)字段划分为不同群体(group)进行分析,如电商领域将全国的总销售额根据省份进行划分,分析各省销售额的变化情况,社交领域将用户根据画像(性别、年龄)进行细分,研究用户的使用情况和偏好,如电信诈骗领域,研究诈骗用户与非诈骗用户的语音通话行为等。在Pandas中,上述的数据处理操作主要运用groupby完成,这篇文章就介绍一下groupby的基本原理、对应的agg、transform和apply操作、groupby后的去重统计及重命名列名。

二、groupby基本原理

模拟的样本数据

import pandas as pd
import numpy as np
#主叫号码 
calling_nbr=["13389012374","13389012375","13389012376","13389012377","13389012379","13389012378","16758439532","16758439533","16758439534","16758439535","16758439536","16758439537"]   
#对端号码
called_nbr=["14374397533","14374397533","14374397533","15926372438","15926372439"] 
#通话时间
start_date=["20230404","20230406","20230408"]
data=pd.DataFrame({
"calling_nbr":[calling_nbr[x] for x in np.random.randint(0,len(calling_nbr),20)],
"called_nbr":[called_nbr[x] for x in np.random.randint(0,len(called_nbr),20)],
"calling_duration":np.random.randint(10,120,20),
"start_date":[start_date[x] for x in np.random.randint(0,len(start_date),20)]})data

在这里插入图片描述
将上面的样本数据集按照start_date字段划分:

group=data.groupby(["start_date"])
group

会得到一个DataFrameGroupBy对象
在这里插入图片描述

如何理解DataFrameGroupBy?对data进行groupby后发生了什么,ipython所返回的结果是其内存地址,并不利于直观地理解,为了看看group内部究竟是什么,把group转为list的形式看看:

list(group)

在这里插入图片描述
转成列表的形式后,可以看到,列表由三个元组组成,每个元组中,第一元素是组别,这里是按时start_date进行分组,所以最后分为了20230404、20230406、20230408,第二个元素的是对应组别下的DataFrame。

总结:groupby的过程就是将原有的DataFrame按照groupby的字段(这里是start_date),划分为若干个分组DataFrame,被分为多少个组就有多少个分组DataFrame。所以说,在groupby之后的一系列操作(如agg、apply等),均是基于子DataFrame的操作。理解了这点,也就基本摸清了Pandas中的groupby操作的主要原理。


三、groupby分组运算

聚合操作是groupby后非常常见的操作,聚合操作可以用来求和、均值、最大值、最小值等,下面的表格列出了Pandas中常见的聚合操作。

函数作用
min最小值
max最大值
sum求和
mean均值
median中位数
std标准差
var方差
count计数

基础聚合操作:只能选择一种聚合操作

单列分组

1、单组其他所有列
按calling_nbr分组(groupby),获取数据表其他所列的统计值。因为called_nbr和start_date不是数字类型,所以会自动忽略。

data.groupby('calling_nbr').mean()

2、单组单列
按calling_nbr分组(groupby),仅获取calling_duration的平均值。

data.groupby('calling_nbr')['calling_duration'].mean()

3、单组多列
按calling_nbr分组(groupby),获取calling_duration和calling_fee列的平均值。

data.groupby('calling_nbr')[['calling_duration','calling_fee']].mean()

多列分组
1、多组其他所有列
按calling_nbr和start_date分组(groupby),获取数据表其他所列的统计值。只针对数字类型的列。

data.groupby(['calling_nbr','start_date']).mean()

2、多组单列
按calling_nbr和start_date分组(groupby),仅获取calling_duration的平均值。

data.groupby(['calling_nbr','start_date'])['calling_duration'].mean()

3、多组多列
按calling_nbr和start_date分组(groupby),获取calling_duration和calling_fee列的平均值。

data.groupby(['calling_nbr','start_date'])[['calling_duration','calling_fee']].mean()

agg 聚合操作:可以针对同列选择不同聚合方法

单列分组

1、单组单列

一种聚合方法,多种写法

比如求主叫号码通话时长的平均值

data.groupby('calling_nbr').agg({'calling_duration':'mean'})data.groupby('calling_nbr')['calling_duration'].agg(['mean'])

多种聚合方法,多种写法

比如:求主叫号码通话时长的平均值,总和和标准差

data.groupby('calling_nbr').agg({'calling_duration':['mean','sum','std']})
data.groupby('calling_nbr').agg({'calling_duration':['mean',np.sum,'std']})data.groupby('calling_nbr')['calling_duration'].agg([np.mean,np.sum,np.std])
data.groupby('calling_nbr')['calling_duration'].agg([np.mean,'sum',np.std])

2、单组多列

一种聚合方法,多种写法

data.groupby('calling_nbr').agg({'calling_duration':['mean'],'calling_fee':['sum']})data.groupby('calling_nbr')[['calling_duration','calling_fee']].agg(['mean'])

多种聚合方法,多种写法

data.groupby('calling_nbr').agg({'calling_duration':['mean','sum','std'],'calling_fee':['mean','sum','std']})
data.groupby('calling_nbr').agg({'calling_duration':['mean',np.sum,'std'],'calling_fee':['mean',np.sum,'std']})data.groupby('calling_nbr')[['calling_duration','calling_fee']].agg([np.mean,np.sum,np.std])
data.groupby('calling_nbr')[['calling_duration','calling_fee']].agg([np.mean,'sum',np.std])

多列分组

1、多组单列

一种聚合方法,多种写法

比如求主叫号码当天通话时长总和

data.groupby(['calling_nbr','start_date']).agg({'calling_duration':'sum'})data.groupby(['calling_nbr','start_date'])['calling_duration'].agg(['sum'])

多种聚合方法,多种写法

data.groupby(['calling_nbr','start_date']).agg({'calling_duration':'sum','calling_duration':np.mean})data.groupby(['calling_nbr','start_date'])['calling_duration'].agg(['sum',np.mean])

2、多组多列

一种聚合方法,多种写法

data.groupby(['calling_nbr','start_date']).agg({'calling_fee':'mean','calling_duration':'mean'})data.groupby(['calling_nbr','start_date'])[['calling_duration','calling_fee']].agg(['mean'])

多种聚合方法,多种写法

比如求主叫号码不同天的主叫次数和平均通话时长,代码如下:

data.groupby(['calling_nbr','start_date']).agg({'calling_fee':'count','calling_duration':'mean'})

比如求主叫号码不同天的主叫次数与通话时长的总和、标准差和平均值

data.groupby(['calling_nbr','start_date']).agg({'calling_fee':['sum','count','mean'],'calling_duration':['sum','count','mean']})data.groupby(['calling_nbr','start_date'])[['calling_duration','calling_fee']].agg(['sum','count','mean'])

注意:对于单组单列的分组来说,基础聚合操作与agg聚合操作,得到的对象有什么不同??

  • 基础聚合操作,由于只选择一列数据,所以生成的对象是Series数据结构。
  • agg聚合操作后生成的对象是DataFrame数据结构。
a=data.groupby('calling_nbr')['calling_duration'].mean()
print(type(a))

在这里插入图片描述

a=data.groupby('calling_nbr')['calling_duration'].agg(['mean'])
a=data.groupby('calling_nbr').agg({'calling_duration':'mean'})
print(type(a))

在这里插入图片描述

transform

在agg 聚合中,我们学会了如何求不同主叫号码同一天的平均通话时长,agg 聚合操作形成的新DataFrame,如果现在需要在原数据集中新增加一列avg_calling_duration,代表主叫号码同一天的平均通话时长(相同一天具有一样的平均通话时长)。

如何实现?

1、正常过程:先求得主叫号码不同天的平均通话时长,然后按照主叫号码和通话时间的对应关系填充到对应的位置

avg_calling_duration=data.groupby(['calling_nbr','start_date'])['calling_duration'].mean().rename("avg_calling_duration").reset_index()data_1 = data.merge(mean_calling_duration) 
data_1

在这里插入图片描述

2、使用transform函数,仅需要一行代码

data['avg_calling_duration']=data.groupby(['calling_nbr','start_date'])['calling_duration'].transform('mean')data

在这里插入图片描述

transform与agg对比

  • 对agg而言,会计算得到不同号码当天的通话时长的均值并直接返回。
  • 对transform而言,则会对第每一条数据求得相应的结果,同一组内的样本会有相同的值,组内求完均值后会按照原索引的顺序返回结果。

可以看下图agg与transform过程图解:

在这里插入图片描述

在这里插入图片描述

apply

对于groupby后的apply,以分组后的子DataFrame作为参数传入指定函数的,基本操作单位是DataFrame。

如果现在需要获取当天主叫与同一个被叫号码的通话次数top1的数据,如何实现?

#统计主叫与同一个被叫号码的通话次数
data['calling_called_max']=data.groupby(['calling_nbr','called_nbr','start_date'])['calling_nbr'].transform('count')#统计主叫与同一个被叫号码的通话次数top1
def get_max_calling_called_num(x):df=x.sort_values(by='calling_called_max',ascending=True)return df.iloc[-1:]get_max_calling_called_num_data=data.groupby(['calling_nbr','called_nbr','start_date'],as_index=False).apply(get_max_calling_called_num)

注意:关于apply的使用,这里有个小建议,虽然说apply拥有更大的灵活性,但apply的运行效率会比agg和transform更慢。所以,groupby之后能用agg和transform解决的问题还是优先使用这两个方法,实在解决不了了才考虑使用apply进行操作。


四、groupby分组后去重统计nunique()

nunique():统计groupby()分组后组内不同值的个数,比如适用于统计主叫号码拨打去重后的对端号码个数。

举例1
要求:统计主叫号码拨打去重后的对端号码个数。

#方法二选一。
data.groupby('calling_nbr')['called_nbr'].nunique()
data.groupby('calling_nbr').agg({ "called_nbr": pd.Series.nunique})

在这里插入图片描述

unique()的区别:unique()方法返回的是去重之后的不同值

data.groupby('calling_nbr')['called_nbr'].unique()

在这里插入图片描述


五、groupby分组后重命名列名

groupby分组后对某列进行聚合计算,需要对聚合计算后的新列进行重命名。

  • 第一:先观察数据类型,要转变为DataFrame数据类型,再重命名。
  • 第二:查看groupby后DataFrame.columns是什么格式。
  • 第三:再选择合适的方法进行重命名。

rename()

rename()重命名,reset_index()将DataFrame的索引转成DataFrame的列。

1、对单列进行重命名。

举例1

data_1=data.groupby('calling_nbr').agg({'calling_duration':'mean'})
print(type(data_1)) #查看数据类型
print(data_1.colunms) #查看列名格式

在这里插入图片描述

我们可以看到,是DataFrame数据类型且DataFrame的列名格式是含单元素的列表,可以直接使用rename重命名。

data_1.rename(columns={'calling_duration':'calling_duration_avg'}).reset_index()

举例2

data_1=data.groupby('calling_nbr')['calling_duration'].mean()
print(type(data_1)) #查看数据类型

在这里插入图片描述

我们可以看到,对单列进行聚合得到是Series数据类型,因此先转换成DataFrame数据类型,再重命名。

data_1.to_frame() #将Series数据类型转成DataFrame数据类型。
data_1.rename(columns={'calling_duration':'calling_duration_avg'}).reset_index()

注意:如果是对单列进行聚合得到是Series数据类型,要先转换成DataFrame数据类型,再重命名。

2、对多列进行重命名

举例1

#两种常用的聚合方法,二选一。
data_1=data.groupby('calling_nbr')[['calling_duration','calling_fee']].mean()
data_1=data.groupby('calling_nbr').agg({'calling_duration':'mean','calling_fee':'mean'})

使用这两种方法都可以对多列进行聚合计算,groupby聚合计算后的数据情况如下。
在这里插入图片描述

print(type(data_1)) #查看数据类型

在这里插入图片描述
都是DataFrame数据类型。

print(data_1.columns) #查看列名格式

在这里插入图片描述
DataFrame的列名格式都是含单元素的列表。

我们可以看到,是DataFrame数据类型且DataFrame的列名格式是含单元素的列表,可以直接使用rename()重命名。

data_1.rename(columns={'calling_duration':'calling_duration_avg','calling_fee':'calling_fee_avg'})

举例2

data_1=data.groupby('calling_nbr')[['calling_duration','calling_fee']].agg(['mean'])
data_1

在这里插入图片描述

print(type(data_1)) #查看数据类型

在这里插入图片描述
是DataFrame数据类型。

print(data_1.columns) #查看列名格式

在这里插入图片描述

查看dataframe的列名格式,发现聚合后的列名是MultiIndex类型。此时,必须通过元组的复合索引方式,才能有效提取列的信息。

data_1.columns.values

在这里插入图片描述
查看列名的元素,我们可以看到每个列都是一个元组。通过下面两种方法都可以重命名:

  • 方法一:通过遍历columns的方式,将MultiIndex的一级和二级索引拼接在一起,作为data的新列名。
data_1.columns=[i[0] + "_" + i[1] for i in data_1.columns]
data_1

在这里插入图片描述

  • 方法二:只需要将元组拼接成字符串,然后替换原来的列名就可以了。
data_1.columns = ['_'.join(col).strip() for col in data_1.columns.values]
data_1

在这里插入图片描述

直接重新命名列名

使用"dataframe.columns=[‘新列名’]或dataframe.columns=pd.Series([‘新列名’])" 重命名。

1、要求:对单列进行重命名。

举例1

#对单列进行聚合计算的两种方式,二选一
data_1=data.groupby('calling_nbr').agg({'calling_duration':'mean'})data_1=data.groupby('calling_nbr')['calling_duration'].mean()
data_1.to_frame()#生成是Series数据类型,因此使用to_frame()转换成DataFrame数据类型。
#直接重命名的两种方法,二选一。
data_1.columns = pd.Series(['calling_duration_avg'])
data_1.columns = ['calling_duration_avg']#reset_index()将DataFrame的索引转成DataFrame的列。
data_1.reset_index(inplace=True) 

2、要求:对多列进行重命名。

举例1

#对多列进行聚合计算的两种方式,二选一
data_1=data.groupby('calling_nbr')[['calling_duration','calling_fee']].mean()
data_1=data.groupby('calling_nbr').agg({'calling_duration':'mean','calling_fee':'mean'})
#直接重命名的两种方法,二选一。
data_1.columns = pd.Series(['calling_duration_avg','calling_fee_avg'])
data_1.columns = ['calling_duration_avg','calling_fee_avg']#reset_index()将DataFrame的索引转成DataFrame的列。
data_1.reset_index(inplace=True) 

举例2

data_1=data.groupby('calling_nbr')[['calling_duration','calling_fee']].agg(['mean'])
print(data_1.columns)  #查看列名格式

在这里插入图片描述
聚合后的列名是MultiIndex类型,不能使用"dataframe.columns=[‘新列名’]或dataframe.columns=pd.Series([‘新列名’])" 直接重命名。要多做一个步骤的处理,可以通过遍历columns的方式,先将MultiIndex的一级和二级索引拼接在一起,作为data的新列名或者先将元组拼接成字符串,再替换原来的列名就可以了。(具体例子见rename()目录下“对多列进行重命名”的举例2

注意

  • 对单列进行重命名,注意基础聚合方法:data_1=data.groupby(‘calling_nbr’)[‘calling_duration’].mean()生成的是Series数据类型。
  • 对多列进行重命名,注意agg聚合方法写法:data_1=data.groupby(‘calling_nbr’)[[‘calling_duration’,‘calling_fee’]].agg([‘mean’]),生成的列名格式是MultiIndex类型,不能直接使用rename方法和"dataframe.columns=[‘新列名’]或dataframe.columns=pd.Series([‘新列名’])" 重命名。

重命名所有的列名:add_prefix() /add_suffix()

在处理大量dataframe数据时,我们可能对所有列名进行重命名操作。

pandas.DataFrame.add_prefix() 函数来修改列名的前缀
pandas.DataFrame.add_suffix() 函数来修改列名的后缀
聚合后的列名是MultiIndex类型,不能使用这种方法。

#三种方法达到效果是一致
data_1=data.groupby('calling_nbr').agg({'calling_duration':'mean','calling_fee':'mean'}).add_prefix('new_')data_1=data.groupby('calling_nbr')[['calling_duration','calling_fee']].mean().add_prefix('new_')data_1=data.groupby('calling_nbr').mean().add_prefix('new_')

在这里插入图片描述

参考文章:

https://zhuanlan.zhihu.com/p/101284491
https://blog.csdn.net/qq_39657585/article/details/114789396
https://blog.csdn.net/yeshang_lady/article/details/105345653
https://blog.csdn.net/weixin_43609275/article/details/86220907
https://blog.csdn.net/weixin_39923556/article/details/123002620
https://blog.csdn.net/pz789as/article/details/106059610
https://zhuanlan.zhihu.com/p/358006128

相关文章:

python利用pandas统计分析—groupby()函数的使用

文章目录 一、groupby使用场景二、groupby基本原理三、groupby分组运算基础聚合操作:只能选择一种聚合操作agg 聚合操作:可以针对同列选择不同聚合方法transformapply 四、groupby分组后去重统计nunique()五、groupby分组后重命名列名rename()直接重新命…...

OPENCV实现ORB特征检测

# -*- coding:utf-8 -*- """ 作者:794919561 日期:2023/8/31 """ import cv2 import numpy as np# 读图像 img = cv2.imread(F:\\learnOpenCV\\openCVLearning\\pictures\\chess.jpg)...

W5100S-EVB-PICO主动PING主机IP检测连通性(十)

前言 上一章节我们用我们开发板在UDP组播模式下进行数据回环测试,本章我们用开发板去主动ping主机IP地址来检测与该主机之间网络的连通性。 什么是PING? PING是一种命令, 是用来探测主机到主机之间是否可通信,如果不能ping到某台…...

使用 Nginx 搭建文件下载服务器

文章目录 一、基础环境二、适用场景三、方法和步骤四、其他说明 版权声明:本文为CSDN博主「杨群」的原创文章,遵循 CC 4.0 BY-SA版权协议,于2023年8月27日首发于CSDN,转载请附上原文出处链接及本声明。 原文链接:http…...

链式栈StackT

C关键词:内部类/模板类/头插 C自学精简教程 目录(必读) C数据结构与算法实现(目录) 栈的内存结构 空栈: 有一个元素的栈: 多个元素的栈: 成员函数说明 0 clear 清空栈 clear 函数负责将栈的对内存释放…...

Fiddler中 AutoResponder 使用

Fiddler的 AutoResponder ,即URL重定向功能非常强大。不管我们做URL重定向,还是做mock测试等,都可以通过该功能进行实践。 下面,小酋就来具体讲下该功能的用法。 Enable rules 启用规则Unmatched requests passthrough 没有匹配…...

77GHz线性调频连续波雷达

文章目录 前言 一、背景 二、优缺点 三、工作原理 四、电路模块设计 4.1.LFMCW信号源 4.2.发射电路 4.3.接收电路 4.4.信号处理器 五、应用 5.1.汽车测距 5.2.军事方面 5.3.气象方面 总结 前言 这篇文章是博主本科期间整理的关于77GHz线性调频连续波雷达的相关资料,…...

YOLOV8改进:更换为MPDIOU,实现有效涨点

1.该文章属于YOLOV5/YOLOV7/YOLOV8改进专栏,包含大量的改进方式,主要以2023年的最新文章和2022年的文章提出改进方式。 2.提供更加详细的改进方法,如将注意力机制添加到网络的不同位置,便于做实验,也可以当做论文的创新点。 2.涨点效果:更换为MPDIOU,实现有效涨点! 目录…...

BookStack开源免费知识库docker-compose部署

BookStack(书栈)是一个功能强大且易于使用的开源知识管理平台,适用于个人、团队或企业的文档协作和知识共享。 一、BookStack特点 简单易用:BookStack提供了一个直观的用户界面,使用户能够轻松创建、编辑和组织文档多…...

Linux:编译遇到 Please port gnulib freadahead.c to your platform ,怎么破

问题背景 编译m4时遇到以下错误,该怎么解决呢? 解决方法 进入m4的build目录:build/host-m4-1.4.17 输入命令: sed -i s/IO_ftrylockfile/IO_EOF_SEEN/ lib/*.c echo "#define _IO_IN_BACKUP 0x100" >> lib/std…...

three.js(三):three.js的渲染结构

three.js 的渲染结构 概述 three.js 封装了场景、灯光、阴影、材质、纹理和三维算法,不必在直接用WebGL 开发项目,但有的时候会间接用到WebGL,比如自定义着色器。three.js 在渲染三维场景时,需要创建很多对象,并将它…...

客户端读写HBase数据库的运行原理

1.HBase的特点 HBase是一个数据库,与RDMS相比,有以下特点: ① 它不支持SQL ② 不支持事务 ③ 没有表关系,不支持JOIN ④ 有列族,列族下可以有上百个列 ⑤ 单元格,即列值,可以存储多个版本的值&…...

不使用VH6501设备,通过VN1630等普通设备使用canConfigureBusOff函数进行busoff干扰测试

** 特别注意一下,使用这个函数需要你的vector驱动在9.6以上以及支持 ISO CAN FD. ** 函数canConfigureBusOff 可以通过脚本的形式产生bus off,而VH6501可以通过干扰bit位来产生bus off(使用CANoe Demo - CANDisturbanceMain进行Bus Off测试)。 对于函数canConfigureBusOf…...

服务器数据恢复-服务器RAID6硬盘故障离线的数据恢复案例

服务器数据恢复环境: 服务器中有一组由6块磁盘组建的RAID6磁盘阵列。服务器作为WEB服务器使用,上面运行了MYSQL数据库以及存放了网站代码和其他数据文件。 服务器故障: 在服务器运行过程中该raid6阵列中有两块磁盘先后离线,但是管…...

DB2 HADR+TSA运维,TSA添加资源组的命令

Tivoli System Automation(TSA)是一个高可用性集群管理软件,DB2 TSAHADR高可用方案可以实现DB2 hadr主备的自动检测切换。本文详细介绍了TSA的常用命令,如何把CDC或者DSG添加到TSA集群中,以及TSA的错误分析方法 常用命令&#xf…...

LeetCode-135-分发糖果

题目描述:n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求,给这些孩子分发糖果: 每个孩子至少分配到 1 个糖果。 相邻两个孩子评分更高的孩子会获得更多的糖果。 请你给每个孩子分发糖果,计…...

Viva Workplace Analytics Employee Feedback SU Viva Glint部署方案

目录 一、Viva Workplace Analytics & Employee Feedback SU Viva Glint介绍 二、Viva Glint和Viva Pulse特点和优势 1. 简单易用...

ASIC-WORLD Verilog(14)系统任务

写在前面 在自己准备写一些简单的verilog教程之前,参考了许多资料----Asic-World网站的这套verilog教程即是其一。这套教程写得极好,奈何没有中文,在下只好斗胆翻译过来(加点自己的理解)分享给大家。 这是网站原文&…...

两台电脑共享文件设置

步骤一:确保网络连接正常,可网线直连。 两台电脑IP设置,例: 步骤二:启用共享功能。 1.在【控制面板】中选择【网络和Internet】; 2.点击【网络和共享中心】,在左侧导航栏中,点击【…...

《C和指针》笔记17:sizeof

sizeof操作符判断它的操作数的类型长度,以字节为单位表示。 操作数既可以是个表达式(常常是单个变量), sizeof x上面的式子返回变量x所占据的字节数。 也可以是两边加上括号的类型名。 sizeof(int)上面的式子返回整型变量的字…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来&#xf…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

Python 训练营打卡 Day 47

注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...

实战设计模式之模板方法模式

概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...