背景
在之前的某个项目中,需要处理从去哪儿网爬取到的房间床型大小数据。
床型大小数据是类似于“双床1.2m”这样的字符串。
产品需要将床型的具体长度数字提取出来展示。
原始的床型大小数据并不理想,有缺失、有特殊符号、不同单位,以及包含多个床型等情况,需要清洗。
示例样本数据如下:
目标
将非规范的原始床型大小数据,处理为:
床型大小只包含“数字”(单位为米),保留小数点后两位数字
多于一种床型大小的情况,用逗号分隔,保留多个数值
床型大小缺失或者没有可用的有效数值时统一为“”(空字符串)
R语言实现
单个向量处理逻辑
把示例样本中多种不同床型的情况,尽可能整合到一个长字符串中(长度为1的字符向量),便于逻辑判断及调试:
在该示例床型大小的字符中,包含多个数字,但只有在 “m” 或者“米”之前的数值才是有效的数值。
提取字符串中符合某个规则的字符,通常使用 包中的 函数。
当需要提出一个字符串中的多个符合规则的子字符串时,使用该包中的 函数。
函数第一个匹配到符合规则的子字符串,因为只有一个值,故而返回的是向量。
函数返回所有匹配到符合规则的子字符串,有可能超过一个值,故而返回的是列表。
提取字符串的正则表达式
这里需要匹配的模式是:“m”或者“米”前面的数字,包含小数点符号。
该匹配模式,在R语言中可通过该 正则表达式实现,说明如下:
是逻辑或的关系,表示“m”或者“米”
是转义字符,通用的正则表达式中的转义是 ,在R语言中是 ;就是改变原定义的含义
表示匹配,原本的字符 转义后在正则表达式中表示 十个数字字符
表示匹配 小数点符号,转义是因为原本的 在正则表达是中被定义为
表示要匹配字符串,后面要跟着“m”或者“米”,但提取的字符串不包括“m”或者“米”这个用来辅助匹配的字符; 其中` 是 模式,后面要跟着 ,但最终匹配的结果不要
关于通用的正则表达式基础知识和用法,可自行在网上搜索“正则表达式”,有很多教程,以及在线测试工具。
在R语言环境中使用正则表达式,推荐参考 官网提供的 “Work with Strings with stringr :: CHEAT SHEET”。
分布实现处理逻辑
载入处理字符常用的包 :
回顾一下之前用来测试验证的整合后的“床型大小”样本数据:
用正则表达式提取符合条件的数字(字符串),结果是列表,用 函数:
将这个列表结果转为向量,用 函数:
保留小数点后两位有效数字:使用函数,其参数 是小数点后保留的位数。
要格式化的是数字的小数点位数,故而先将格式化的对象转为数值(之前从字符串中提取出来的结果是字符串),用 函数:
将多个床型大小的数字首尾相连拼接成长字符串,使用 函数,这里需要指定参数 作为连接字符串中间的分隔符号。
函数与基础包中的 函数用法相同。
这里使用 函数,是要保持所有字符处理都使用 包处理的统一风格,并强化 的使用。
启用 参数,表示将字符向量中的元素拼接在一起,变成函数(对包含多个元素的向量应用函数后返回只有一个元素的向量结果)。
使用另外一个参数 ,表示多个向量字符串各元素拼接,是函数(每个元素分别对应拼接,并返回等长的向量结果)。
主要注意的是, 和 两个参数是互斥的,不能同时使用。
在进行以上处理后,原始床型大小数据变成了规范的结果。
处理逻辑函数化
为了使得处理过程更为方便的应用在多个元素的向量上,需要将处理逻辑函数化。
另一方面,为了使得处理过程的代码可读性更强,在如下函数中引入 这个 符号(管道符):其作用是将左边的对象(上一个对象),传递给右边的函数(下一个函数),作为后续函数的第一个参数的值。
该 管道符号最初是由 包开发,现已流行成为R语言中的一个重要功能符号,以致于很多包都内置了这个 管道符号,例如在 包中也已经内置了该 管道符号可直接使用,无需再额外引用 包。
在单个字符向量上应用 函数:
在函数应用到多个元素的向量时,函数中 会将所有的单个元素拆分的结果合并成了一个长度为一的单元素向量,虽然结果没有报错,但并不与输入的每个元素一一对应。
正确的用法是使用 来应用 函数在向量的每个元素上。
函数向量化
为了使得所定义的函数更简化及便于调用,将 过程内嵌在 内部使其向量化:
在将函数向量化之后,就可以直接像普通的函数一样使用 函数 :
在数据框中调用函数:
总结
该案例中主要使用了 包中的 函数,配合正则表达式及 模式来提取所需的字符。
在函数定义中使用了 管道符合增加代码逻辑的可读写,并最后将函数向量化便于调用。
领取专属 10元无门槛券
私享最新 技术干货