救援计划(十三)——提取字符串中的数字并计算
最近发现身边很多朋友不愿意用,转而转向其他数据操作库。 作为一名数据工作者,我基本上是张口闭嘴,所以我写了这个系列,让更多的朋友爱上他们。
系列文章说明:
系列名称(系列文章的序号)——本系列文章具体解决的需求
平台:
/数据要求
需要从后面的字符串中提取出统一格式的数字并进行计算。
import pandas as pd
df = pd.DataFrame({
'年区间': ['1年以内', '无要求', '1-3年', ' 3-5年 ', '5年以上'],
'薪资': ['1.3-1.5万/月', '6-8千/月', '1.3万/月', '20-30万/年', ' 30-50万/年 ']
})
df
/ 需求拆解
正如标题提到从字符串中提取数字,可以遍历列,一一判断,取出数字。 而且上面提到了统一格式的数据,但是给出的数据似乎并不统一。 你是在唬人吗?
从单个数据点来判断有点困难,这里我不提供这个想法的代码。 想了想,整体来说,正则表达式还是蛮适合提取这种格式的字符串数据的。 救援计划(七)中也简单提到了正则表达式的使用——将包含金额符号的字符串列转换为浮点类型数据。 这次我们就通过本文的例子来看看如何提取正则表达式。 到所需的数量并进行后续计算。
/需求处理
①是
首先,观察数据结构。 字符串中有数字,也有没有数字。 对于那些没有数字的,将其替换为 0。将包含数字的中间部分分开可能会很有用。 您可以考虑使用以下正则表达式:
import re
re.compile(r'(\d+)?-?(\d+)')
我不确定中间的-什么时候会出现。 如果出现,它只会出现一次,所以添加一个 ? 在最后。 前面的数字也是不可预测的。 添加 ? 以同样的方式。 使用括号表示需要提取括号内的数据。 虽然可以给提取出来的数据加上括号做标签,但是这里不需要这样做,能够区分就可以了。
目前有一个想法,计算提取年份的平均值,如果出现0.5,则四舍五入为整数年数。 将上述正则表达式应用于以下函数。 因为提取的是数字或字符串格式,所以需要强制转换为整数类型。
import re
def year_average(data):
search_year = re.search(r'(\d+)?-?(\d+)', data)
def average(args):
# 平均值计算
x = tuple(args)
length = len(x)
return round(sum(x) / length, 0)
# 如果能提取到数字则计算平均值
if search_year:
return average([int(i) for i in search_year.groups() if i])
# 否则返回 0
else:
return 0
df['平均年数'] = df['年区间'].apply(year_average)
运行后数据显示:
通过apply调用该函数,可以进行定时查找、提取并完成后续的计算。 逻辑比较清晰,容易理解。 这个在之前的救援计划(七)——将包含金额标记的字符串列转换为浮点类型数据中已经提到过。 如果 pd。 class是一种类型或类型,它有一个.str方法,可以对字符串进行一些特征操作。 还有一个提取函数.str.,也可以使用正则表达式。
②.str。
df_dash = df['年区间'].str.extract(r'(\d+)?-?(\d+)')
已成功提取。 接下来的操作与re部分相同。 将其转换为浮点数据,然后计算平均值。 可以看到行号为1的行中,两列都是np.nan,所以计算完之后,仍然是np.nan,np.nan需要补0,计算结果进行四舍五入。
df['平均年数2'] = df_dash.astype(float).mean(axis=1).fillna(0).round(0)
df
结果与上次计算一致。
(手动水印:原CSDN死者派、公众号派)
在工资列中,您会注意到数字之间有更多的小数点。 仅小数点就很容易解决。 为了和年度范围列的提取有点不同,需要将年薪转换为月薪,并以数字的形式显示。
最初的想法是分别提取数字和汉字。 由于两者都需要参与计算,所以我们可以先将它们替换为数字,然后将它们作为一个整体提取出来。 在“Wan”和“Qian”之前添加分隔符,以避免与前一个分隔符混淆。 分隔符可以用在正则表达式中。 不属于元字符的范畴。
# 先替换成数字,regex=True,用正则方式匹配
df_dash = df['薪资'].replace({'万': '@10000', '千': '@1000', '月': '1', '年': '12'}, regex=True)
仔细一看,正则表达式如下:
re.compile(r'(\d+\.?\d*)?-?(\d+\.?\d*)?@(\d+)/(\d+)')
使用 .str. 提取:
df_dash = df_dash.str.extract(r'(\d+\.?\d*)?-?(\d+\.?\d*)?@(\d+)/(\d+)').astype(float)
正如预期,生成了 4 列数据。 提取后采用类型转换的方式,类型均为float类型。
换算成月薪:
df_dash.apply(lambda x: (x[[0, 1]] * x[2]) / x[3], axis=1)
通过以上一系列操作,最终将字符串类型数据转换为浮点数字格式,达到了想要的结果。
/ 总结
这里我们主要使用.str。 方法结合正则表达式提取相关信息。 如果想了解更多使用场景,可以查看官方文档。 使用这种方法需要对正则表达式有高度的掌握,并且需要了解字符串之间的关系。 最小相似类型,写出适当的表达式,完成数据提取。
采桑显春,移云遮日。
写于 2022 年 4 月 18 日