Python项目实战 —— 淘宝用户行为分析

article/2025/9/12 7:18:08

Python项目实战

  • Python项目实战 —— 0淘宝用户行为分析

一、背景

   本数据集共有大约1200万条数据,数据为淘宝APP2014年11月18日至2014年12月18日的用户行为数据,字段分别是:user_id用户身份(已脱敏)、item_id商品ID(已脱敏)、behavior_type用户行为类型(包含点击、收藏、加购物车、支付四种行为,分别用数字1、2、3、4表示)、user_geohash地理位置、item_category品类ID(商品所属的品类)、time用户行为发生的时间。

二、解题思路

   本文从以下几个角度,对淘宝用户进行行为分析:

① 不同维度用户行为数据;

② 用户感兴趣的商品品类;

③ 漏斗分析;

④ RFM分析;

三、数据分析

3.1 数据清洗

查重 ➜ 缺失值处理 ➜ 数据加工(如时间字段的处理、astype等)

import numpy as np
import pandas as pd
import matplotlib.pyplot as pltdf = pd.read_csv('/xxx/recommend_user.csv',parse_dates=['time'])
df['date'] = df.time.dt.date
df['hour'] = df.time.dt.hourprint('文件中有{}行重复数据,已删除.'.format(len(df[df.duplicated()])))
df.drop_duplicates(inplace=True,ignore_index=True)
df.drop(['user_geohash','time'],axis=1,inplace=True)

3.2 数据分析

3.2.1 用户整体行为分析

   在此期间,用户的行为如下:访问次数是748w,访问人数是1w,人均访问次数是747.9次,数据详情如图所示…

3.2.2 用户每日行为分析

   自进入12月开始,访问次数和人数逐渐上升,且在双十二当天达到峰值,访问次数约43w次、人数约7.7k人,购买量1.4w件;此外,在双十二的前后一周内,每日的数据基本大于等于均值。    付费率=付费人数/总人数,当日点击且购买的付费率均值是23.8%,当月点击且购买的付费率均值是77% (11月是72.4%,12月是81.8%)。

3.2.3 用户每时行为分析

  • 05-10点:人们逐渐醒来开始上班,利用路程时间访问app,访问人数和次数都在持续上升;
  • 10-17点:人们工作时间,利用空闲时间访问app,访问人数和次数都处于平稳状态;
  • 17-22点:人们下班有大量空余时间,可访问app购买自己所需商品,访问人数缓慢上升,但访问次数上升明显的,且在21&22点达到峰值;在此时间段购买量和人均购买次数都高于均值且上升明显;
  • 22-05点:因开始休息了,故访问人数和次数都在持续下降;

3.2.4 用户对商品品类的挑选分析

   在点击量和购买量前20的品类中,相同的品类共计有14种(已标星);    在点击量top20中,有7种商品的购买率低于均值;    在购买量top20中,有12种商品的购买率低于均值;

3.2.5 漏斗分析

   点击→收藏的转化率:3.22%    点击→加入购物车的转化率:4.46%    点击→支付的转化率:1.48%    建议:增加跨店满减、收藏加购送商品赠品、送福利等活动,引导用户收藏加购行为,从而提高用户购买转化率。

3.2.6 用户分类(RFM分析)

   RFM分析步骤:①计算R/F/M值;②根据打分规则,分别计算Score_R/F/M;③根据平均值,分别计算Result_R/F/M(得分大于均值标记为2,反之为1);④计算RFM得分,并给客户分类;

  • 占比最多的是重要发展客户,这类客户消费频次低,我们需要提升他们的消费频率,可通过优惠券叠加等活动来刺激消费;
  • 其次是重要挽留客户,这类客户消费时间间隔较远,且消费频次低,需要主动联系客户(如短信、邮件、APP推送等),调查清楚哪里出现了问题;
  • 重要价值用户是优质客户,可以有针对性地给这类客户提供VIP服务,如淘宝VIP会员卡等等;
  • 重要保持客户,这类客户消费时间间隔较远,但是消费频次高,有可能就是需要买东西的时候,就高频购买,不需要就不再购物,对于这类客户,需要主动联系,了解客户的需求,及时满足这类用户的需求(提供优惠券促使消费);

四、建议

   综上,我的建议是:

① 在大促前,制定回报率高的活动(如淘宝的猫猫升级活动,可分为个人战和团队战,不同战队制定不同方案等);在大促后,给用户推荐购买量/点击量高且优惠的产品,达到刺激用户登陆app,从而提高访问量和访问次数的目的;

② 一天内用户最活跃的时间段是21-22点,可把握该黄金时段,集中进行营销活动提高用户购买转化率,如平台带货直播、分会场促销、限时抢购等。此外,可进行进一步分析,不同时间段进行不同推荐;

③ 关于热搜和热销商品,可加大优惠力度、精准匹配用户、针对点击量高而购买转化率低的商品可改善商品页、详情页以及评论区管理等,促使用户购买;

④ 针对不用客户实行不同运营策略,详见3.2.6 用户分类(RFM分析);

五、代码

5.1 代码-用户整体行为

s = '{}~{}期间,用户行为分析:'.format(df.date.min(),df.date.max())
s1 = '访问次数\n{}'.format(df[df.behavior_type==1].user_id.count())
s2 = '访问人数\n{}'.format(df[df.behavior_type==1].user_id.nunique())
s3 = '购买量\n'+str(df[df.behavior_type==4].item_id.count())
s4 = '购买人数\n{}'.format(df[df.behavior_type==4].user_id.nunique())
s5 = '人均访问次数:{}'.format(round(df[df.behavior_type==1].user_id.count()/df[df.behavior_type==1]\.user_id.nunique(),1))
s6 = '人均购买次数:'+str(round(df[df.behavior_type==4].item_id.count()/df[df.behavior_type==1].user_id.nunique(),1))
s7 = '付费用户人均购买次数:'+str(round(df[df.behavior_type==4].item_id.count()/df[df.behavior_type==4]\.user_id.nunique(),1))
s8 = '付费率:{}%'.format(round(df[df.behavior_type==4].user_id.nunique()/df.user_id.nunique()*100,2))plt.text(0,1,s,bbox=dict(facecolor='yellow',alpha=0.8),size=28)
plt.text(0.1,0.7,s1,size=28)
plt.text(0.6,0.7,s2,size=28)
plt.text(1.1,0.7,s3,size=28)
plt.text(1.6,0.7,s4,size=28)
plt.text(0.1,0.4,s5,size=28)
plt.text(1.1,0.4,s7,size=28)
plt.text(0.1,0.1,s6,size=28)
plt.text(1.1,0.1,s8,size=28)
plt.axis('off')
#plt.savefig('1.png',dpi=150,bbox_inches='tight')

5.2 代码-用户每日行为

d1_1 = df[df.behavior_type==1].groupby('date').agg({'user_id':['count','nunique']})
d1_2 = df[df.behavior_type==4].groupby('date').agg({'user_id':['count','nunique']})
d1 = pd.concat([d1_1,d1_2],axis=1)
d1.columns = ['pv','uv','buy_count','buy_uv']
d1['人均访问次数'] = round(d1.pv/d1.uv,2)
d1['人均购买次数'] = round(d1.buy_count/d1.uv,2)
d1['付费率'] = round(d1.buy_uv/d1.uv*100,2)plt.figure(figsize=(24,12))  # 全局标题用plt.suptitle 每个子图的标题用plt.title
plt.suptitle('淘宝用户每日访问情况',fontsize=20,color='r',backgroundcolor='yellow')
plt.subplot(2,2,1)
plt.xticks(rotation=90)
plt.plot(d1.index.astype(str),d1.pv,'.-',label='pv')
plt.axhline(d1.pv.mean(),linestyle='--',label='pv均值')
plt.text(0,d1.pv.mean(),str(round(d1.pv.mean(),1)),fontsize=16)
plt.legend()
plt.subplot(2,2,2)
plt.xticks(rotation=90)
plt.plot(d1.index.astype(str),d1.uv,'.-',label='uv')
plt.axhline(d1.uv.mean(),linestyle='--',label='uv均值')
plt.text(0,d1.uv.mean(),str(round(d1.uv.mean(),1)),fontsize=16)
plt.plot(d1.index.astype(str),d1.buy_uv,'.-',label='buy_uv')
plt.axhline(d1.buy_uv.mean(),color='orange',linestyle='--',label='buy_uv均值')
plt.text(0,d1.buy_uv.mean(),str(round(d1.buy_uv.mean(),1)),fontsize=16)
plt.legend()
plt.subplot(2,2,3)
plt.xticks(rotation=90)
plt.plot(d1.index.astype(str),d1.人均访问次数,'.-',label='人均访问次数')
plt.axhline(d1.人均访问次数.mean(),linestyle='--',label='人均访问次数均值')
plt.text(0,d1.人均访问次数.mean(),str(round(d1.人均访问次数.mean(),1)),fontsize=16)
plt.plot(d1.index.astype(str),d1.付费率,'.-',label='付费率')
plt.axhline(d1.付费率.mean(),color='orange',linestyle='--',label='付费率均值')
plt.text(0,d1.付费率.mean(),str(round(d1.付费率.mean(),1)),fontsize=16)
plt.legend()
plt.subplot(2,2,4)
plt.xticks(rotation=90)
plt.plot(d1.index.astype(str),d1.buy_count,'.-',label='buy_count')
plt.axhline(d1.buy_count.mean(),linestyle='--',label='buy_count均值')
plt.text(0,d1.buy_count.mean(),str(round(d1.buy_count.mean(),1)),fontsize=16)
plt.legend(loc='upper left')
plt.twinx()
plt.plot(d1.index.astype(str),d1.人均购买次数,'.-',color='orange',label='人均购买次数')
plt.axhline(d1.人均购买次数.mean(),color='orange',linestyle='--',label='人均购买次数均值')
plt.text(0,d1.人均购买次数.mean(),str(round(d1.人均购买次数.mean(),1)),fontsize=16)
plt.ylim([0,2])
plt.legend()
#plt.savefig('2.png',dpi=150,bbox_inches='tight')
# 当日点击&购买的付费率
df1 = df[df.behavior_type==1][['user_id','item_id','date']].drop_duplicates()
df2 = df[df.behavior_type==4][['user_id','item_id','date']].drop_duplicates()
df1['合并'] = df1.user_id.astype(str)+'&'+df1.item_id.astype(str)+'&'+df1.date.astype(str)
df2['合并'] = df2.user_id.astype(str)+'&'+df2.item_id.astype(str)+'&'+df2.date.astype(str)
df3 = pd.merge(df1,df2,how='left',on='合并')
df4 = pd.concat([df1.groupby('date').agg({'user_id':'nunique'}),df3[df3.user_id_y.notna()].groupby('date_x').agg({'user_id_x':'nunique'})],axis=1)
df4['rate'] = round(df4.user_id_x/df4.user_id*100,2)
df4.columns = ['uv','buy_uv','rate']
df4.plot(kind='line',secondary_y=['rate'],figsize=(16,4))

5.3 代码-用户每时行为

d2_1 = df[df.behavior_type==1].groupby('hour').agg({'user_id':['count','nunique']})
d2_2 = df[df.behavior_type==4].groupby('hour').agg({'user_id':['count','nunique']})
d2 = pd.concat([d2_1,d2_2],axis=1)
d2.columns = ['pv','uv','buy_count','buy_uv']
d2['人均访问次数'] = round(d2.pv/d2.uv,2)
d2['人均购买次数'] = round(d2.buy_count/d2.uv,2)
d2['付费率'] = round(d2.buy_uv/d2.uv*100,2)plt.figure(figsize=(24,12))  # 全局标题用plt.suptitle 每个子图的标题用plt.title
plt.suptitle('淘宝用户每时访问情况',fontsize=20,color='r',backgroundcolor='yellow')
plt.subplot(2,2,1)
plt.plot(d2.index.astype(str),d2.pv,'.-',label='pv')
plt.axhline(d2.pv.mean(),linestyle='--',label='pv均值')
plt.text(0,d2.pv.mean(),str(round(d2.pv.mean(),1)),fontsize=16)
plt.legend()
plt.subplot(2,2,2)
plt.plot(d2.index.astype(str),d2.uv,'.-',label='uv')
plt.axhline(d2.uv.mean(),linestyle='--',label='uv均值')
plt.text(0,d2.uv.mean(),str(round(d2.uv.mean(),1)),fontsize=16)
plt.plot(d2.index.astype(str),d2.buy_uv,'.-',label='buy_uv')
plt.axhline(d2.buy_uv.mean(),color='orange',linestyle='--',label='buy_uv均值')
plt.text(0,d2.buy_uv.mean(),str(round(d2.buy_uv.mean(),1)),fontsize=16)
plt.legend()
plt.subplot(2,2,3)
plt.plot(d2.index.astype(str),d2.人均访问次数,'.-',label='人均访问次数')
plt.axhline(d2.人均访问次数.mean(),linestyle='--',label='人均访问次数均值')
plt.text(0,d2.人均访问次数.mean(),str(round(d2.人均访问次数.mean(),1)),fontsize=16)
plt.plot(d2.index.astype(str),d2.付费率,'.-',label='付费率')
plt.axhline(d2.付费率.mean(),color='orange',linestyle='--',label='付费率均值')
plt.text(0,d2.付费率.mean(),str(round(d2.付费率.mean(),1)),fontsize=16)
plt.legend()
plt.subplot(2,2,4)
plt.plot(d2.index.astype(str),d2.buy_count,'.-',label='buy_count')
plt.axhline(d2.buy_count.mean(),linestyle='--',label='buy_count均值')
plt.text(0,d2.buy_count.mean(),str(round(d2.buy_count.mean(),1)),fontsize=16)
plt.legend(loc='upper center')
plt.twinx()
plt.plot(d2.index.astype(str),d2.人均购买次数,'.-',color='orange',label='人均购买次数')
plt.axhline(d2.人均购买次数.mean(),color='orange',linestyle='--',label='人均购买次数均值')
plt.text(0,d2.人均购买次数.mean(),str(round(d2.人均购买次数.mean(),1)),fontsize=16)
plt.legend()
plt.ylim([0,1])
#plt.savefig('3.png',dpi=150,bbox_inches='tight')

5.4 代码-用户对商品品类的挑选

d3_1 = df[df.behavior_type==1].groupby('item_category').user_id.count().rename('click')
d3_2 = df[df.behavior_type==4].groupby('item_category').user_id.count().rename('buy')
d3 = pd.merge(d3_1,d3_2,how='left',left_index=True,right_index=True).fillna(0)
d3['rate'] = round(d3.buy/d3.click*100,2)
m = d3.sort_values('click',ascending=False).head(20)
n = d3.sort_values('buy',ascending=False).head(20)
mn_i = list(set(m.index.astype(str))&set(n.index.astype(str)))
mn_v = list(m.loc[eval(i),'click'] for i in mn_i)plt.figure(figsize=(16,10))
plt.suptitle('商品品类Top20(标星的是在点击&购买中都出现的品类)',fontsize=20,color='r',backgroundcolor='yellow')
plt.subplot(2,1,1)
plt.title('点击量Top20的品类\n')
plt.bar(m.index.astype(str),m.click,alpha=0.5,label='点击量')
plt.bar(m.index.astype(str),m.buy,label='购买量')
plt.scatter(mn_i,mn_v,c='r',marker='*',label='标星') #必须放后面,若放前面:前14个柱子都标星,出现错误
plt.legend()
plt.twinx()
plt.plot(m.index.astype(str),m.rate,'g',label='购买率%')
plt.axhline(m.rate.mean(),linestyle='--',label='购买率均值')
plt.legend()
plt.subplot(2,1,2)
plt.title('\n购买量Top20的品类\n')
plt.bar(n.index.astype(str),n.click,alpha=0.5)
plt.bar(n.index.astype(str),n.buy)
plt.scatter(mn_i,mn_v,c='r',marker='*')
plt.twinx()
plt.plot(n.index.astype(str),n.rate,'g',)
plt.axhline(n.rate.mean(),linestyle='--')
#plt.savefig('4.png',dpi=150,bbox_inches='tight')

5.5 代码-用户分类(RFM分析)

print('\033[5;30;43mRFM分析:\033[0m')
print('\033[30;43m1.计算R/F/M值;\n2.根据打分规则,分别计算Score_R/F/M;\033[0m')
print('\033[30;43m3.根据平均值,分别计算Result_R/F/M(得分大于均值标记为2,反之为1);\n4.计算RFM得分,并给客户分类;\033[0m')
Score_dict = {222:'重要价值客户',122:'重要保持客户',212:'重要发展客户',112:'重要挽留客户',\221:'一般价值客户',121:'一般保持客户',211:'一般发展客户',111:'一般挽留客户'}d5_1 = df[df.behavior_type==4].groupby('user_id').agg({'date':'max','item_id':'count'})
d5_1.columns = ['buydate_max','F']
d5_1['R'] = (pd.to_datetime('2014-12-31')-pd.to_datetime(d5_1.buydate_max)).dt.daysd5 = d5_1[['R','F']].reset_index()
#可根据 plt.hist(d5.R,bins=5)和实际意义,来确定labels(也可看看pd.cut/pd.qcut)
d5['Score_R'] = pd.cut(d5.R,bins=15,labels=sorted(list(range(1,16)),reverse=True)).astype(float)
d5['Score_F'] = pd.cut(d5.F,bins=15,labels=list(range(1,16))).astype(float)
d5['Result_R'] = d5.Score_R.apply(lambda x:2 if x>d5.Score_R.mean() else 1)
d5['Result_F'] = d5.Score_F.apply(lambda x:2 if x>d5.Score_F.mean() else 1)
d5['Result_M'] = 2 #原数据没有金额,此处人工标记为2
d5['Score_RFM'] = d5.Result_R*100+d5.Result_F*10+d5.Result_M
d5['客户类型'] = d5.Score_RFM.map(lambda x:Score_dict[x])print('\033[5;30;43m\n按客户类型汇总:\033[0m')
d6 = d5.groupby('客户类型').agg({'user_id':'count','R':'mean','F':'mean'}).round(2)
d6.columns = ['人数','间隔天数','购买次数']
d6

大家可以关注我 ,我们也会同步更新此文章,项目领取可以私我哦~

谢谢大家


http://chatgpt.dhexx.cn/article/xUR3RSEu.shtml

相关文章

Python实战小项目

不是很稀饭《复联》嘛,看了《复联4》,就用50行Python代码做了这些: 视频展示:50行代码玩转《复仇者联盟》 教程地址:图片转字符画 相关教程地址:视频转字符动画 当然,这个仅仅是初学者的一个…

手把手教导实战Python Web项目

手把手教导实战Python Web项目 一、前言 Django是一个开放源代码的Web应用框架,由Python写成。采用了MVC的框架模式,即模型M,视图V和控制器C。Django的主要目的是简便、快速的开发数据库驱动的网站。它强调代码复用,多个组件可以很…

Python web开发之flask项目实战总结

在线问答系统 Flask Web开发项目介绍功能描述一、前端设计二、数据库设计三、页面功能开发1.用户模块2.问答模块 四、总结 Flask Web开发 请求到响应 用户通过浏览器访问url,会发送请求到服务器,服务器接收请求后会根据url规则找到对应的视图函数进…

Python必学的4个实战项目,拿走不谢

最近遇到了一些比较经典的实战项目,比较适合零基础的小白以及基础较薄弱的小伙伴。想了想,我决定把它分享给大家。 Python是一种极具可读性和通用性的编程语言。Python这个名字的灵感来自于英国喜剧团体Monty Python,它的开发团队有一个重要的…

菜鸟进阶高手, 推荐 7 个 Python 上手实战项目

作为一个语法简洁、有着丰富的第三方库的编程语言,Python 上手极为简单,短时间内就可以让你编写出能够解决实际问题的小程序,甚至去面试初级 Python 工程师的职位。 不过,如果要写出一些更复杂的应用,或者想从事数据分…

比金典还经典——4个python项目实战

写在前面的一些P话: Python是一种极具可读性和通用性的编程语言。Python这个名字的灵感来自于英国喜剧团体Monty Python,它的开发团队有一个重要的基础目标,就是使语言使用起来很有趣。Python易于设置,并且是用相对直接的风格来编…

Python项目实战 4.1:账号登录

目录 一、用户名登录 二、多账号登录 三、首页用户名展示 四、退出登录 五、判断用户是否登录 一、用户名登录 1. 用户名登录逻辑分析 2. 用户名登录接口设计 1. 请求方式 选项方案请求方法POST请求地址/login/ 2. 请求参数:表单 参数名类型是否必传说明usern…

Python爬虫实战

文章目录 1. 引言2. 页面分析2.1 页面元素分析2.2 分页分析2.3 页面详情页面2.4 下载链接 3. 代码3.1 数据库结构3.2 步骤3.2.1 根据url获取页面结构3.2.2 解析页面数据3.2.3 数据存入数据库 4. 测试结果5. 完整代码 1. 引言 注:勿用于非法用途。 之前学习过Pytho…

insert into

7.insert into 如果我们想向表格中插入数据,就需要用到insert into语句了 7.1 insert into语法 INSERT INTO 表名 VALUES (值1, 值2,....) (注:插入一行数据) INSERT INTO 表名 (列名, 列名…

LaTeX: Missing } or { inserted. ^^I\For

报错 分析 可以发现,报错提示缺少{,但第306行并没有问题,并不缺少大括号。 这种情况下,很有可能是前面某个公式处出现了大括号缺失,建议从头到尾查找一遍。 修改 往前排查后发现某一处缺少大括号,如下所…

sqlserver触发器的使用以及inserted和deleted详解

背景:最近在项目中有需求是当人员表中有变动时(比如:增加人员、修改人员信息、删除人员信息)需要把这张表中的变动的信息同步到它对应的日志表中。那么如果用代码写逻辑的话在执行效率上会比较慢,正好sqlserver提供了触…

insert和insertSelective区别

使用逆向工程生成的代码做一个添加时通常都会给出两个答案&#xff0c;如题目想要增加一条数据会让你选择insert或者insertSelective 两者的区别在于如果选择insert 那么所有的字段都会添加一遍即使没有值 <insert id"insert" parameterType"com.ego.pojo.Tb…

Inserted和Deleted在insert、update、delete的简单使用

Inserted和Deleted在insert、update、delete的简单使用 Inserted表和Deleted表,仅仅在触发器运行时存在。当insert、update、delete操作时&#xff0c;可使用借助两个表来输出&#xff08;使用OUTPUT关键字&#xff09;操作前后的数据的变化。 Insert Update Delete Insert…

定义自定义指令;inserted()、update()

自定义指令的意义&#xff1a;对普通DOM元素进行底层操作&#xff1b; 作用 &#xff1a;可以获取到底层的dom&#xff0c;拿到想要的节点&#xff0c;从而进行操作&#xff1b; 实际应用&#xff1a;可以通过指令知道什么时候dom创建完成&#xff0c;从而进行依赖dom的库的初…

29.VUE自定义指令directive和inserted

VUE自定义指令directive和inserted 1.什么事自定义指令1.2使用自定义指令的方式 2.设置自定义组件2.1 设置全局指令2.2 设置私有指令2.3 钩子函数3. 案例 1.什么事自定义指令 指令 (Directives) 是带有 v- 前缀的特殊特性。指令特性的值预期是单个 JavaScript 表达式 (v-for 例…

echarts中x轴 y轴配置(字体颜色,线的颜色,分割线,y周单位颜色)。vue中直接使用echarts以及vue中使用vue-echarts如何配置横向渐变与纵向渐变(后者适用于前者)

vue中直接使用echarts //var myChart this.$echarts.init(document.getElementById("echart-twoline")); //vue var myChart echarts.init(document.getElementById("echart-twoline"));//jquery var option {backgroundColor: "#323a5e",…

Echarts折线图X轴Y轴图例位置调整

当X轴数据过多时Echarts会默认显示一半 如下图只显示奇数月份 Echarts加入axisLabel然后将interval设置为0就会将横轴全部显示 看一下效果 但是信息太多,看起来黏在了一起,我们可以让它-30度角倾斜显示 同样在axisLabel将rotate设置为-30,再看一下效果 这下都显示出来的,但…

修改echarts的x轴y轴的刻度和刻度线文本颜色和xy轴的轴线颜色和标题title的字体颜色

1&#xff0c;x轴y轴都是一样的&#xff1a; 1.1修改刻度文本颜色&#xff1a; 找到xAxis和yAxis&#xff1a; 添加如下代码&#xff1a;&#xff08;和data和type同级并列&#xff09; axisLabel: {show: true,textStyle: {color: #fff} } 如图&#xff1a; 1.2修改xy轴的轴…

转:echarts图表x,y轴的设置

转自&#xff1a; https://www.cnblogs.com/cjh-strive/p/11065005.html 每到用echarts这门技术去画图的时候&#xff0c;我们大多人都是直接从echarts的官网的案例找相应的案例直接把代码复制到开发软件上基本随便一改就能使用&#xff0c;但是这种情况基本都是在练习的时候和…