在构建高效的数据剖析体系时,咱们经常会遇到两个中心概念:目标(Metrics) 和 标签(Tags) 。目标是对事务功用的量化衡量,它们协助咱们追寻关键事务方针的达到状况。例如,咱们可能会重视用户增长率、产品销售额或客户的增续投等目标。这些数字方针为咱们供给了事务运转的直观快照,并允许咱们对成功与否进行量化评估。
而标签,则是附加在目标上的文字描述,用于对数据进行分类和上下文化。它们像是数据的特点,使咱们可以从不同的视点切入,对目标进行深化剖析。例如,关于销售额这一目标,咱们可以使用“地区”、“产品线”、“客户集体”等标签来细分市场体现。通过这种方法,咱们不仅可以了解整体的销售状况,还可以洞悉到哪些产品在特定区域或客户集体中最受欢迎,然后做出愈加精细化的事务决策。
在实际使用中,目标和标签的联系可以类比于坐标系中的点和坐标轴。目标代表了咱们要追寻的具体数值,而标签则界说了坐标系中的各个维度,协助咱们定位和解说这些数值。没有标签,咱们只能得到一个孤立的数字;而有了标签,咱们就可以将这个数字放置在一个多维度的空间中,了解其背面的含义和价值。
客户标签不仅是数据价值体现的关键途径,更是咱们今日谈论的中心所在。那在数据仓库中,通过分层、归类、建模会计算出一系列的目标,而标签则可以使用pandas将目标转化为对应的标签。
上篇现已解说了pandas的几个办法,许多朋友好奇学会了,适用的场景在哪呢,这就听我娓娓道来。
先打个底:以了解为主,不行谨慎,假如看完还是不会,那一定是我讲的不行好。我会尽可能对相对复杂的代码加入注释,欢迎大家谈论区彼此沟通啊。
一、对类别型目标进行值的替换
该函数用于对类别型目标进行值的替换,举个比方,假定用户的星座对应的字典如下:
"cnstll": {"白羊座":"11","金牛座":"12","双子座":"13","巨蟹座":"14","狮子座":"15","处女座":"16", "天枰座":"17","天蝎座":"18","射手座":"19","摩羯座":"20","水瓶座":"21","双鱼座":"22","其他":"99","NULL":"99"},
importpandasaspd
defcat_process(df,cat_dict):
'''
该函数用于对类别型目标进行值的替换,其间:
df:dataframe,传入待处理的dateframe,有必要包含待替换的目标列
cat_dict:dict类型,key代表待替换的目标称号,value代表用于替换的一一对应的值的联系词典
联系词典中有必要包含“其他”和"NULL"两个key。
原数据中没有“其他”的在“其他”中填入和“NULL”key对应的相同的value
returndf:传入的df中在cat_dict中存在的目标的值已被替换成为对应标签的值
'''
forkey,cat_valincat_dict.items():
#df[key]取某一列的值df[key].map(cat_val)依据这个字典或函数对Series(索引 值)中的每个元素进行映射或转化
df[key]=df[key].map(cat_val)
#将空值替换成其他,inplace=True:表明对DataFrame进行原地修正,即不创立新的副本
df[key].fillna(cat_val['其他'],inplace=True)
#将数据类型转化为int64
df[key]=df[key].astype('int64')
returndf
#创立测试数据
data={
'姓名':['张三','李四','王五','赵六','钱七'],
'星座':['狮子座','天蝎座','双子座','摩羯座','水瓶座']
}
df=pd.DataFrame(data)
#星座的字典
cat_dict={
"星座":{
"白羊座":"11",
"金牛座":"12",
"双子座":"13",
"巨蟹座":"14",
"狮子座":"15",
"处女座":"16",
"天枰座":"17",
"天蝎座":"18",
"射手座":"19",
"摩羯座":"20",
"水瓶座":"21",
"双鱼座":"22",
"其他":"99",
"NULL":"99"
}
}
#调用cat_process函数
processed_df=cat_process(df,cat_dict)
#打印处理后的DataFrame
print(processed_df)
运转成果
姓名星座
0张三15
1李四18
2王五13
3赵六20
4钱七21
可能会有人提出疑问:为什么要阅历这样的转化过程?将中文值转化为数字岂非添加了复杂性?但是事实并非如此。选用数字存储具有以下几点优点:
- 存储功率: 数字通常比文本占用更少的存储空间。使用数字代码可以减少数据库的存储需求,进步存储功率。
- 查询功用: 数字类型的数据在数据库中进行查询和排序时比文本类型更快。这关于需要频频进行数据剖析和报告的大型数据集特别重要。
- 数据一致性: 使用数字代码可以避免因为文本标签的不同写法(如大小写、空格、特别字符等)引起的数据不一致问题。
- 安全性: 在某些状况下,将敏感信息(如客户信息)以数字代码的方法存储可以进步数据的安全性。
- 数据处理: 在进行数据剖析和发掘时,数字类型的数据更简单进行计算和计算,如使用聚合函数、履行数学运算等。
- 扩展性: 数字代码可以更简单地扩展以习惯新的标签或分类,而不需要修正数据库结构。
-
兼容性: 数字代码可以与不同的数据库体系和数据剖析东西兼容,便于数据的迁移和交流。
总的来说,将客户标签存储为数字可以进步数据库的功率、节省存储空间,一起有助于保护客户隐私和简化数据处理过程。
这一种办法适用于多种场景,比方客户来历、公司类型、寓居省份、性别、属相等等。
二、对数值型目标进行缺失值的填充和分箱处理
该函数用于对数值型目标进行缺失值的填充和分箱处理,举个比方,咱们对客户的最终一笔买卖距今时长做一个分箱处理:
区间对应的字典值如下:
标签编码 | 标签值 |
---|---|
11 | 1年以下 |
12 | [1年,3年) |
13 | [3年以上) |
99 | 未出资 |
那咱们的履行代码如下:
importpandasaspd
importnumpyasnp
defnum_process(df,num_dict,num_null):
'''
该函数用于对数值型目标进行缺失值的填充和分箱处理,其间:
df:dataframe,传入待处理的dateframe,有必要包含待分箱的目标列
num_dict:dict类型,key代表待分箱的目标称号,value代表分箱的切分点
tag_null:dict类型,key代表待分箱的目标称号,value代表该目标下需独自分组的缺失值
returndf:传入的df中在num_dict中存在的目标的值已被替换成为对应标签的值
'''
#num_dict:{'last_trans_mon_dur':[0,12,36,inf]}
forkey,cat_valinnum_dict.items():
null_ind=[]
ifnum_null.get(key)isnotNone:
#找到数据框中列为key且数值等于num_null[key]的行的索引,并转化为列表方法。例如[0,1,2]此处代表找出和json文件中缺失值一样的数据对应的索引
null_ind2=list(df[df[key]==num_null[key]].index)#首要是找出不正常的数据脏数据,假如数据质量不错,这里就不会履行
#将数据框中列为key且数值等于num_null[key]的值替换为98。其间num_null里键key对应的值inplace=True代表在原数据上修正,默以为False
df[key].replace(num_null[key],98,inplace=True)
null_ind.extend(null_ind2)#将列表往后扩展
print("①.null_ind:%s"%null_ind)
df[key]=df[key].astype('str')#将数据框类型转化为str
df[key].replace('NULL','99',inplace=True)#数据框中目标为key且数值等于'NULL'的值替换为99。
null_ind1=list(
df[df[key]=='99'].index)#找到数据框中列为key且数值等于99的行的索引,并转化为列表方法。例如[0,1,2]目的也是为了找出null的数据
null_ind.extend(null_ind1)
this_col=df[key].astype('float')#将数据框类型转化为浮点型例如99-99.0
print("②.this_col:%s"%this_col)
print("☆₊⁺₊⁺✩。⋆✰⋆⁺₊⋆†☾⋆☆₊⁺₊⁺✩。⋆✰⋆⁺₊⋆†☾⋆☆₊⁺₊⁺✩。⋆✰⋆⁺₊⋆†☾⋆☆₊⁺₊⁺✩。⋆✰⋆⁺₊⋆†☾⋆☆₊⁺₊⁺✩。⋆✰⋆⁺₊⋆†☾⋆☆₊⁺₊⁺✩。⋆✰⋆⁺₊⋆†☾⋆")
unnull_ind=df.index.difference(null_ind)#查找两个索引的集合差异
print("③.unnull_ind:%s"%unnull_ind)
print("④.this_col[unnull_ind]:%s"%this_col[unnull_ind])
print("⑤.cat_val,:%s"%cat_val)
#对非缺失值进行分箱处理,使用pd.cut()函数将数值分箱,参数right=False表明左闭右开区间,生成的标签从11开端递增。
'''
cat_val:[0,12,36,inf]
range(11,10 len(cat_val)):range函数,生成一个从11开端、到10 len(cat_val)-1结束的整数序列。
其间,len(cat_val)表明分箱的数量,加上10是为了保证生成的标签与分箱的数量对应,而且从11开端编号。
str(x)for这部分是一个列表推导式的语法结构,表明对range()生成的每个元素x履行字符串化操作,并将成果组成一个新的列表。
假如cat_val是[0,12,36,float('inf')],那么生成的标签就是['11','12','13']。
['11','12','13']因为这一列为last_trans_mon_dur最终一笔买卖距今时长cat_val为[0,12,36,inf]
所以pd.cut切割的区间为[0,12),[12,36),[36,float('inf'))
对应的字典值为1年以下[1年,3年)[3年以上)
'''
this_col[unnull_ind]=pd.cut(this_col[unnull_ind],cat_val,right=False,
labels=[str(x)forxinrange(11,10 len(cat_val))])
#this_col[unnull_ind]此时为last_trans_mon_dur列转化后的数值即从原来的月份小数转化为了111213
df[key]=this_col.astype(
'int64')#将last_trans_mon_dur的新值赋予df中last_trans_mon_dur这一列,一起转化为将数据类型转化为int64
returndf
#创立测试数据
data={
'name':['张三','李四','王五','赵六'],
'last_trans_mon_dur':[2,18,-2,30]
}
df=pd.DataFrame(data)
#界说分箱字典和缺失值字典
num_dict={'last_trans_mon_dur':[0,12,36,np.inf]}
num_null={'last_trans_mon_dur':-2}
#处理数据
processed_df=num_process(df,num_dict,num_null)
#打印成果
print(processed_df)
运转成果
①.null_ind:[2]
②.this_col:02.0
118.0
298.0
330.0
Name:last_trans_mon_dur,dtype:float64
☆₊⁺₊⁺✩。⋆✰⋆⁺₊⋆†☾⋆☆₊⁺₊⁺✩。⋆✰⋆⁺₊⋆†☾⋆☆₊⁺₊⁺✩。⋆✰⋆⁺₊⋆†☾⋆☆₊⁺₊⁺✩。⋆✰⋆⁺₊⋆†☾⋆☆₊⁺₊⁺✩。⋆✰⋆⁺₊⋆†☾⋆☆₊⁺₊⁺✩。⋆✰⋆⁺₊⋆†☾⋆
③.unnull_ind:Int64Index([0,1,3],dtype='int64')
④.this_col[unnull_ind]:02.0
118.0
330.0
Name:last_trans_mon_dur,dtype:float64
⑤.cat_val,:[0,12,36,inf]
namelast_trans_mon_dur
0张三11
1李四12
2王五98
3赵六12
清楚明了,成果现已发生了明显的改变:本来的具体数值现已转化为了标签编码。例如,本来数值为2个月的数据,现在对应的标签编码为11,代表着1年以下的时长。
将目标转化为标签编码有几个优点:
- 简化解说: 标签编码将本来复杂的数值转化为了易于了解的分类标签,使得数据解说愈加直观和简单。
- 下降差错: 通过将接连的数值转化为有限的分类,可以下降因为数据差错或丈量不准确性而引起的影响。
- 增强模型泛化能力: 在某些机器学习模型中,将目标转化为标签编码可以进步模型的泛化能力,使其更习惯不同的数据散布和模式。
-
便利数据剖析: 标签编码使得数据更简单被聚合和比较,然后便利进行数据剖析和可视化。
这样表达愈加明晰,也更简单了解。
这一种办法适用于多种场景,比方用户年纪(少年、青年、中青年、中年、中晚年、晚年)、当时客户价值等级(优质活跃客户、优质潜力客户、优质坚持客户、优质款留客户、一般…、低价值…)、客户贡献度等级(高忠实、一般忠实、低忠实)、当时客户贡献度等级环比趋势(上升、稳定、下降)等等。
三、对数值型目标进行判别
该函数用于对数值型目标进行判别,大于输入的词典中的阙值的判别为1,否则为0。
举个比方,现在要断定客户是否为存续客户,假如存续金额>0则为1,否则为0。
importpandasaspd
defboo_process(df,boo_dict):
'''
该函数用于对数值型目标进行判别,大于输入的词典中的阙值的判别为1,否则为0,其间:
df:dataframe,传入待处理的dateframe,有必要包含待处理的目标列
boo_dict:dict类型,key代表待判别的目标称号,value代表该目标对应的阙值
returndf:传入的df中在num_dict中存在的目标的值已被替换成为对应标签的值
'''
forkey,valinboo_dict.items():
print("布尔目标:%s"%key)
df[key].replace('NULL',0,inplace=True)#NULL值转化为0
df[key]=(df[key]>val).astype('int64')#查找df[key]对应的值中大于0的都标记为1
returndf
#生成测试数据
data={'姓名':['张三','李四','王五'],
'存续金额':[200000,880000,0]}
df=pd.DataFrame(data)
#界说阈值字典存续金额
boo_dict={'存续金额':0}
df_processed=boo_process(df,boo_dict)
print(df_processed)
运转成果
布尔目标:存续金额
姓名存续金额
0张三1
1李四1
2王五0
清楚明了,成果现已发生了明显的改变:本来的具体数值现已转化为了0和1。
这一种办法适用于多种场景,比方前史最大买卖金额(以100万为阈值,大于100万为1,反之为0)、是否购买过美妆(以美妆买卖金额0为阈值,大于0为1,反之为0)等等。
四、json文件装备及读取
学习了上述三个办法后,您会发现其实传入的数据都是以 JSON 文件的方法供给的。为了下降后期的运维本钱并进步代码的标准性,可以将需要处理的同类型目标统一放在 JSON 文件中。
例如,可以创立几个 JSON 文件,文件名分别为:
- 布尔型标签.json
{
"max_trans_amt":"最大买卖金额",
"max_trans_amt":10000000
}
- 数值型标签.json
{
"his_max_aum_amt":"前史最大存续金额"
,"his_max_aum_amt":[0,0.0001,1000000,3000000,6000000,10000000,30000000,60000000,100000000,Infinity]
,"year_old":"年纪"
,"year_old":[0,18,30,45,60,75,Infinity]
}
- 特别缺失值.json
{
"curr_hold_amt_mom":"当时存续财物金额环比"
,"curr_hold_amt_mom":-2
,"curr_hold_amt_yoy":"当时存续财物同比"
,"curr_hold_amt_yoy":-2
}
- 类别型标签.json
{
"gender":"性别",
"gender":{"男":"1","女":"0","其他":"9","NULL":"9"},
"zodiac":"属相",
"zodiac":{"11":"11","12":"12","13":"13","14":"14","15":"15","16":"16",
"17":"17","18":"18","19":"19","20":"20","21":"21","22":"22","其他":"99","NULL":"99"},
"cnstll":"星座",
"cnstll":{"白羊座":"11","金牛座":"12","双子座":"13","巨蟹座":"14","狮子座":"15","处女座":"16",
"天枰座":"17","天蝎座":"18","射手座":"19","摩羯座":"20","水瓶座":"21","双鱼座":"22","其他":"99","NULL":"99"},
"ctry":"居民身份",
"ctry":{"我国":"1","我国香港和我国澳门":"2","我国台湾":"3","其他":"4","NULL":"9"},
"prov":"寓居省份",
"prov":{"北京":"11","天津":"12","河北":"13","山西":"14","内蒙古":"15"
,"辽宁":"21","吉林":"22","黑龙江":"23","上海":"31","江苏":"32","浙江":"33"
,"安徽":"34","福建":"35","江西":"36","山东":"37","河南":"41","湖北":"42"
,"湖南":"43","广东":"44","广西":"45","海南":"46","重庆":"50","四川":"51"
,"贵州":"52","云南":"53","西藏":"54","陕西":"61","甘肃":"62","青海":"63"
,"宁夏":"64","新疆":"65","其他":"98","NULL":"99"},
"city":"城市类别",
"city":{"北京":"1","上海":"1","广州":"1","深圳":"1",
"成都":"2","重庆":"2","杭州":"2","武汉":"2","西安":"2","天津":"2","姑苏":"2","南京":"2","郑州":"2","长沙":"2","东莞":"2","沈阳":"2","青岛":"2","合肥":"2","佛山":"2",
"宁波":"3","昆明":"3","福州":"3","无锡":"3","厦门":"3","济南":"3","大连":"3","哈尔滨":"3","温州":"3","石家庄":"3","泉州":"3","南宁":"3","长春":"3","南昌":"3","贵阳":"3","金华":"3",
"常州":"3","嘉兴":"3","南通":"3","徐州":"3","太原":"3","珠海":"3","中山":"3","保定":"3","兰州":"3","台州":"3","绍兴":"3","烟台":"3","廊坊":"3","其他":"4","NULL":"9"},
"mrtl_stat":"婚姻状况",
"mrtl_stat":{"02":"1","01":"2","其他":"9","NULL":"9"}
}
在任何状况下,都应该考虑下”Why”,这样做的优点其实是多方面的:
- 下降保护本钱: 将目标信息保存在外部 JSON 文件中,减少了直接修正代码的需求。假如需要新增或许修正目标,只需修正对应的 JSON 文件,不用改动代码逻辑,下降了保护本钱。
- 进步代码标准性: 将目标信息和代码逻辑别离,使代码愈加明晰易懂,符合杰出的编程标准和设计准则,便于团队协作和后续保护。
- 灵敏性和可扩展性: 通过 JSON 文件动态加载目标信息,使得体系愈加灵敏可装备,便于应对不同的需求和改变。新增目标或修正阈值只需更新 JSON 文件,无需修正代码,进步了体系的可扩展性和习惯性。
既然有了json文件,代码天然要添加一块读取的功用
importos,json
data_file_path_test=r"D:codetest"
withopen(os.path.join(data_file_path_test,'特别缺失值.json'),encoding="utf-8")asf:#类别型标签_itg
cat_dict=json.load(f)#将文件中的JSON数据加载并解析成Python目标字典值
print(cat_dict)
运转成果
{'curr_hold_amt_mom':-2,'curr_hold_amt_yoy':-2}
五、pandas横表转竖表
最终这段代码的首要作用是将数据从横表转化为竖表,这样做是为了在处理完客户标签后,以竖表的方法更明晰地展示数据。
importpandasaspd
defdataframe_transfer(df,tag_nm,key_list=['cust_no','crt_dt','cust_crm_no'],var_nm='tag_cd',
value_nm='tag_val_cd'):
'''
该函数用于将标签横表转化为竖表,其间:
df:dataframe,传入待处理的dateframe
tag_nm:list类型,代表标签称号
key_list:list类型,不做处理的关键字段列表,默以为['cust_no','crt_dt','cust_crm_no']
var_nm:str类型,转化后生成的新标签列称号,默以为'tag_cd'
value_nm:str类型,转化后生成的新标签值列称号,默以为'tag_val_cd'
returndf:传入的df后边新增处理完的新标签
'''
col=[]
col.extend(key_list)
col.extend(tag_nm)
ddf=df.loc[:,col].copy()
ddf.loc[:,tag_nm]=ddf.loc[:,tag_nm].astype(str)
ddf=pd.melt(ddf,id_vars=key_list,value_vars=tag_nm,var_name=var_nm,value_name=value_nm)
returnddf
#创立测试数据
data={
'cust_no':[1,2,3,4],
'crt_dt':['2024-01-01','2024-01-02','2024-01-03','2024-01-04'],
'cust_crm_no':['CRM001','CRM002','CRM003','CRM004'],
'tag1':['A','B','C','D'],
'tag2':['X','Y','Z','W']
}
df=pd.DataFrame(data)
#显现原始数据
print("原始数据:")
print(df)
#调用函数进行转化
tag_nm=['tag1','tag2']
result_df=dataframe_transfer(df,tag_nm)
#打印转化后的成果
print("n转化后的成果:")
print(result_df)
运转成果
原始数据:
cust_nocrt_dtcust_crm_notag1tag2
012024-01-01CRM001AX
122024-01-02CRM002BY
232024-01-03CRM003CZ
342024-01-04CRM004DW
转化后的成果:
cust_nocrt_dtcust_crm_notag_cdtag_val_cd
012024-01-01CRM001tag1A
122024-01-02CRM002tag1B
232024-01-03CRM003tag1C
342024-01-04CRM004tag1D
412024-01-01CRM001tag2X
522024-01-02CRM002tag2Y
632024-01-03CRM003tag2Z
742024-01-04CRM004tag2W
今日的解说就进入尾声了,本篇介绍了如何使用Pandas将目标数据巧妙地转化为标签。这仅仅Pandas在数据处理中的一个简单使用场景,而Pandas在Python数据剖析和数据科学领域的功用远不止于此。希望大家可以坚持对Python的探索和学习热心,继续深化了解和使用Pandas,一起在数据科学领域不断进步。