抛出问题
倘若现在我们有以下的表格,我们要使用机器学习的模型对它进行建模分析(标签未列出),然后看到这些文字特征我们首先第一反应就是对它进行One-Hot处理。
城市 | 食品 | 饮品 |
---|---|---|
广州 | 牛奶 | 果汁 |
深圳 | 面包 | 椰汁 |
北京 | 烤鸭 | 二锅头 |
武汉 | 热干面 | 牛奶 |
汕头 | 牛肉丸 | 牛肉汤 |
One-Hot后的结果就变成了
城市 | 食品 | 饮品 |
---|---|---|
0001 | 0001 | 0100 |
0010 | 0010 | 0010 |
0011 | 0011 | 0011 |
0100 | 0100 | 0001 |
0101 | 0101 | 0101 |
这只是简单的One-Hot处理,我们把相同的东西用同样的One-Hot编码替代,但我们从表格中可以看出,牛奶在食品中出现过,在饮品中也出现过,它在One-Hot之后的值是一样的,都是0001。
类似相关的问题例如基因,当出现了等位基因的情况,或者是A染色体上的某个基因的代号与B染色体上的某个基因代号是相同的时候,我们要如何得知,该基因在One-Hot了之后的重要性到底是多少呢?
然后,找了很多资料,写了个代码如下:Python能力不强,代码写的有点笨,有建议可以评论一下。
import re
import numpy as np
import pandas as pd
df = pd.read_csv('.\\bingli.csv', header=None, encoding='gbk').fillna('nan').values
# 声明存放无重复列名的列表
# fea = [[]]
# 声明存放新列名的列表
ndf = []
kf = []
# 在df表的列进行循环
for i in range(0, len(df[0])):
# 声明基因的名称的列表
ldf = []
# 将列名取出来
locname = df[0][i]
# 在df表的行创建循环
for j in range(len(df)):
# 取出每个基因的名称
name = df[j][i]
# 跳过列名,且删除掉字段中的'\t'字符
if j != 0:
name = str(re.sub(r'\D', "", df[j][i]))
# 如果基因的名称不在列表中且不为nan和空格,则加入列名列表中
if name not in ldf and name != 'nan' and name != "":
ldf.append(name)
# print(sorted(ldf))
# 使用fea列表存储列名,用于统计
# fea.append(ldf)
# 将列名排序后,为每个列名加上基因名称的后缀
for k in sorted(ldf):
if k == locname:
pass
else:
kf.append(locname + '_' + k)
ndf.append(kf)
# =============================================================================
# 在原表df中按行循环:
# 取出每个列的列名和编码
# 使用if语句进行判读
# =============================================================================
for i in range(1, len(df)):
tmp = []
indexs = []
# 从原表的行中按个循环
for j in range(len(df[i])):
# 获取基因编码和列名
feaname = df[i][j]
colname = df[0][j]
if feaname == "" or feaname == 'nan':
pass
else:
# 去除基因编码的多余WhiteSpace等,仅保留数字
feaname = str(re.sub(r'\D', "", feaname))
# 判断否个特征的数据是否出现过,如出现了,则找出它的index
for k in range(len(ndf[0])):
if ndf[0][k].startswith(colname) and ndf[0][k].endswith(feaname):
# print(ndf[0][k], colna, feaname, k,)
indexs.append(k)
# 根据index给样本加1
for h in range(len(ndf[0])):
if h in indexs:
tmp.append(1)
else:
tmp.append(0)
ndf.append(tmp)
这个代码的效果主要是,将这种格式的数据
变成:
也就是使用特征名称加上数据组合成新的特征,然后在样本中出现过的标为1,否则为0。
其实我现在有点犹豫,这么做到底有没有意义?Catboost是可以直接跑,只要设置特征列就好了,其他的模型就不行,但是这样处理后就会造成一个数据稀疏的问题,毕竟一行的1太少了,而0太多了。