ps: 以后我把遇到的处理稀奇古怪数据的思路放在知乎以供参考

原始数据(主要展现了需要操作处理的列, 好友一个文本内容列就隐藏了):

目标

将数据以[文本id 标签, 是否解决问题] 这三个特征, 转化为方便原始数据随时随地选取某一具体标签, 放入模型内, 帮助其完成对某一标签的二分类预测

id 标签 是否解决问题

12910 价格,购车流程,金融 0,0,0

9808 价格,内饰,动力,操控 0,0,1,1

深思熟虑后, 考虑到既要能展示标签的大致情况

又要方便数据随时选择选择某一具体标签然后摘选出来随时处理

因此最终确定了下列各式:

id 价格 购车流程 金融 内饰 动力 操控....

12910 0 0 0 None None None

9808 0 None NOne 0 1 1

这么一个小问题, 可是不好搞啊, 不知道各位有没有一个清晰的思路去处理. 反正我是花了几个小时在互联网的帮助下,才搞定.

思路

1: 首先是将里面多标签的数据和单一标签的数据分开

# 根据标签内容是否包含',' 然后创建一个新列, 一次为基础划分

df['get_multiple_labels'] = df['labels'].apply(

lambda x: 1 if ',' in x else 2

)

one_labels_data = df.loc[df['get_multiple_labels'] == 2].copy()

2: 将多标签的数据拆分开来

id 标签 是否解决

123 a,b,c 1,0,1

变成如下格式:

id 标签 是否解决

123 a 1

123 b 0

123 c 1

代码:(这里再次感谢牛逼的pandas和友好的互联网学友)

df['labels'] = df['labels'].apply(

lambda x: x.split(',') if ',' in x else x

)

df['solve'] = df['solve'].apply(

lambda x: x.split(',') if ',' in x else x

)

# 首先将字符串形式的标签和是否解决以标点号为切割

变成如下形式

id 标签 是否解决

123 [a,b,c] [1,0,1]

# 然后将其展开(这里是我从网络上找到的方法)

df = pd.DataFrame({'id': df.id.repeat(df.labels.str.len()),

'labels': np.concatenate(df.labels.values),

'solve': np.concatenate(df.solve.values)})

# 效果自己造一批数据自己看很神奇, 但是需要确保 长度一致

df = pd.concat([df, one_labels_data])

# 最后将两者数据合并即可

df['solve'] = df['solve'].apply(

lambda x: '-1' if x == '0' else x

)

# 为什么要将原本的1,0变为1,-1且为字符串形式算是一个有趣的问题

# 如果您有兴趣不妨考虑一下

3: 将标签变为特征列, 解决为1, 未解决为0 不存在为np.nan

# 此时我们的数据格式如下

id 标签 是否解决

123 a 1

123 b 0

123 c 1

# 那么接下来的问题就是怎么生成所有的标签列, 以及怎么将labels和是否解决放入到对应的标签列力

# 获取所有的标签, 简单

labels = df.labels.values

labels = np.unique(",".join(labels).split(','))

# 生成新的标签列, 简单, 但是将其对应的是否解决的值放入内部, 就比较麻烦了

# 如果只是单纯的判断一个文本id下对应了那些标签有的话在新的标签列设为1没有设为0, 这个很简单

for label in labels:

df[label] = df['labels'].apply(

lambda x: 1 if x == label else 0

)

# 但是没用啊, 我们需要的是即判断了id维度下都有那些标签存在

# 还要有该标签对应的是否解决值

# 好好想如果是你 该怎么做?

# 其实我们知道lambda一次一次只能针对一个对象处理, 当然你也可以设置一函数, 但是仔细想想

# 是不是还是没办法将三者(标签列, 标签, 是否解决)砸一个函数内按照我们的需求去处理?

# 既然如此干脆在新建一个列来帮助却对标签列下面到底该填什么值算求

def labels_solve(label, solve):

# if ',' in solve:

# solve = solve.split(',')

# solve = solve[0]

# 这一步是因为我的数据会存在一些问题

return [label, int(solve)]

df['label_solve'] = df.apply(

lambda x: labels_solve(x['labels'], x['solve']), axis=1

)

# 这下子我们直接针对列来和标签列做交互不就完全没问题了吗

for label in labels:

df[label] = df['label_solve'].apply(

lambda x: x[1] if x[0] == label else None

)

4: 最后的处理

# 此时你讲获取到以下类型的数据

id 价格 优惠政策 保险 内饰 加装改装 动力 外观 操控 空间 竞品对比 经销商试驾 置换 蜘蛛智选

1500 NaN 1.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

1500 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 1.0

1590 NaN NaN NaN 1.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN

1590 NaN NaN NaN NaN NaN 1.0 NaN NaN NaN NaN NaN NaN NaN

1590 NaN NaN NaN NaN NaN NaN 1.0 NaN NaN NaN NaN NaN NaN

1590 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 1.0

1672 NaN NaN NaN NaN NaN NaN NaN 1.0 NaN NaN NaN NaN NaN

1672 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN -1.0 NaN NaN

# 嗯有内味道了, 但是他这一行一个标签值, 感觉不太对劲啊

# 如果直接拿着这去和原始数据合并的话,啧啧, 希望你的数据不够大,并且电脑足够好

# 不然卵用没有, 还会卡死电脑

# 现在就是想办法把数据以文本id为维度, 合并行了

# 不多BB

columns = ['价格', '优惠政策', '保险', '内饰', '加装改装', '动力', '外观', '操控', '空间', '竞品对比',

'经销商试驾', '置换', '蜘蛛智选', '质保', '购车流程', '配置', '金融']

df = df[columns].groupby(df['id']).sum()

df.columns = columns

df.reset_index(inplace=True)

for column in columns:

df[column] = df[column].apply(

lambda x: 0 if int(x) < 0

else 1 if int(x) >= 1

else np.nan

)

# 最后的效果如下

id 价格 优惠政策 保险 内饰 加装改装 动力 外观 操控 空间 竞品对比 经销商试驾 置换 蜘蛛智选 \

1493 1.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN 1.0 NaN NaN

1500 1.0 1.0 NaN NaN NaN NaN NaN 1.0 NaN NaN NaN NaN 1.0

1504 NaN 1.0 NaN NaN NaN NaN NaN NaN NaN NaN 1.0 NaN NaN

1566 NaN NaN NaN NaN NaN NaN NaN NaN 1.0 NaN NaN NaN 1.0

1581 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN 1.0 NaN NaN

这次的数据处理过程, 比较困难的是如何设置标签数据的最终格式, 正如前文所说既要方便看到标签在文本id中的大致情况, 还要方便后续数据针对某一个或者某几个标签做连接, 最终选定了上面的格式

后续如果我只希望拿到价格标签的数据做处理的话

我只需要

data = pd.merge(datas, labels_datas[['id', '价格']], on=['id'], how='left'])

data.dropna(subset=['价格'], inplace=True)

即可拿到那一部分我们需要的数据, 因此我个人还是很满意这次的效果.

因此记录(并装B)