需求和场景:
某些数据字段会出现不同的值,比如以下数据
上海白玉兰计算机有限公司
上海市白玉兰计算机有限公司
中国科学院广州地化学研究所
中国科学院广州地球化学研究所
中国科学院广州地球化学研究所
中国科学院广州地化学研究所
吉林省福春木业有限公司
吉林省富春木业有限公司
河北富华康土特环保有限公司
富华康土特环保有限公司
中国科学院地球化学研究所
中国科学院广州地球化学研究所
深圳艾捷科技有限责任公司
深圳艾捷科技有限公司
大连工美企业有限责任公司
大连工美企业有限公司
芜湖市永嘉制衣有限公司
芜湖市永嘉制衣有限责任公司
中国科学院广州地球化学研究所
中国科学院地球化学研究所
这类数据有各特点就是差异很小,这样的数据可以通过字符的 edit distance 来表示相似度,通过过滤排序即可做一些简单处理,edit distance 是指针对字符串 A ,通过 insert , replace, delete 操作后变为 B 的步骤数,数值越低则表示两个字符串越相思,本文使用 commons-text 包中的 LevenshteinDistance 来计算字符串的 edit distance,数据集合内容如下:
sn,title
1,南昌市西湖区桃花医院
2,汉中汉台区宗营信用社公路街分社
3,费县探沂镇中心卫生院
4,广东省邮政公司揭阳市惠来县葵潭邮政局
5,深圳新合程供应链股份有限公司
6,中山市美立电器有限公司
7,青岛钢铁有限公司
8,台州市永耀塑业有限公司
9,永嘉县巨霸鞋业有限公司
10,芜湖市永嘉制衣有限公司
11,陕西天禄堂制药有限公司
...
下载地址:http://orfuc602j.bkt.clouddn.com/data-sets/repeat/repeat-500
解决思路:加载文件后,使用笛卡尔乘积获得任意两个公司数据的集合,然后计算 edit distance, 再排序输出即可,
mavn 依赖:
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.1.1</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.mongodb.spark</groupId>
<artifactId>mongo-spark-connector_2.11</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-mllib_2.11</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.8</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.1</version>
</dependency>
java 代码如下:
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.text.similarity.LevenshteinDistance;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import java.io.Serializable;
/** * Created by liangdi on 6/12/17. */
@Slf4j
public class EditDistanceTest {
public static void main(String[] args) {
JavaSparkContext ctx = SparkUtil.createContext();
/** * 数据结构 * sn,title * 1,南昌市西湖区桃花医院 2,汉中汉台区宗营信用社公路街分社 3,费县探沂镇中心卫生院 4,广东省邮政公司揭阳市惠来县葵潭邮政局 5,深圳新合程供应链股份有限公司 6,中山市美立电器有限公司 7,青岛钢铁有限公司 8,台州市永耀塑业有限公司 9,永嘉县巨霸鞋业有限公司 10,芜湖市永嘉制衣有限公司 11,陕西天禄堂制药有限公司 */
JavaRDD<String> file = ctx.textFile("data-sets/repeat/repeat-500");
JavaRDD<ComInfo> companyList = file.map(line -> {
String[] split = line.split(",");
return new ComInfo(split[0], split[1]);
});
// 笛卡尔乘积,建立任意两个公司关联的数据 companyList.cartesian(companyList)
// 过滤掉 同一个公司的数据 .filter(tuple -> !tuple._1.sn.equals(tuple._2.sn))
.map((tuple) -> {
LevenshteinDistance levenshteinDistance = new LevenshteinDistance();
// 使用 commons-text 包进行字符串 Edit Distance 计算 Integer distance = levenshteinDistance.apply(tuple._1.title, tuple._2.title);
//由于是笛卡尔乘积,所以需要 使用两个公司数据的sn排序后作为 group 字段最终进行分组,不然就会出现重复数据,两公司一前一后出现两次 String sn;
if (tuple._1.sn.compareTo(tuple._2.sn) > 1) {
sn = tuple._1.sn + tuple._2.sn;
} else {
sn = tuple._2.sn + tuple._1.sn;
}
return new ComDistance(tuple._1.title, tuple._2.title, sn, distance);
})
// 选出 Edit Distance 为 (0,5] 之间的数据, 0 的话为相同,这样的数据不需要 .filter(companyDistance -> companyDistance.distance <= 5 && companyDistance.distance > 0)
.groupBy(companyDistance -> companyDistance.sn)
.map(groupTuple -> groupTuple._2.iterator().next())
// 使用计算好的 Edit Distance 排序 .sortBy(companyDistance -> companyDistance.distance, true, 0)
.saveAsTextFile("data-sets/repeat/result.txt");
/*.foreach(companyDistance -> { log.info("Edit Distance:{}", companyDistance.distance); log.info("{}", companyDistance.tital_1); log.info("{}", companyDistance.tital_2); });*/
}
public static class ComInfo implements Serializable {
String sn;
String title;
ComInfo(String sn, String title) {
this.sn = sn;
this.title = title;
}
@Override
public String toString() {
return "ComInfo{" +
"sn='" + sn + '\'' +
", title='" + title + '\'' +
'}';
}
}
public static class ComDistance implements Serializable {
String tital_1;
String tital_2;
String sn;
Integer distance;
ComDistance(String tital_1, String tital_2, String sn, Integer distance) {
this.tital_1 = tital_1;
this.tital_2 = tital_2;
this.sn = sn;
this.distance = distance;
}
@Override
public String toString() {
return "Edit Distance " + distance + "\n" +
tital_1 + "\n" +
tital_2 + "\n";
}
}
}
计算结果:
Edit Distance 1
上海白玉兰计算机有限公司
上海市白玉兰计算机有限公司
Edit Distance 1
中国科学院广州地化学研究所
中国科学院广州地球化学研究所
Edit Distance 1
中国科学院广州地球化学研究所
中国科学院广州地化学研究所
Edit Distance 1
吉林省福春木业有限公司
吉林省富春木业有限公司
Edit Distance 1
南通市九色鹿业有限公司
南通九色鹿业有限公司
Edit Distance 1
淮安中洪建设有限公司
淮安市中洪建设有限公司
Edit Distance 1
深圳太立德仁文化传播有限公司
深圳市太立德仁文化传播有限公司
Edit Distance 1
青岛欲太工贸发展有限公司汽车修理厂
青岛裕太工贸发展有限公司汽车修理厂
Edit Distance 1
东台市中微特电机厂
东台中微特电机厂
Edit Distance 1
汕头市金砂中医医院
汕头市金砂中医院
Edit Distance 1
杭州祐康电子商务网络有限公司
杭州佑康电子商务网络有限公司
Edit Distance 1
浙江九康电器有限公司
浙江九康电气有限公司
Edit Distance 1
东台中微特电机厂
东台市中微特电机厂
Edit Distance 1
杭州佑康电子商务网络有限公司
杭州祐康电子商务网络有限公司
Edit Distance 1
莱芜市泰东汽车销售服务有限公司
莱芜泰东汽车销售服务有限公司
Edit Distance 1
青岛裕太工贸发展有限公司汽车修理厂
青岛欲太工贸发展有限公司汽车修理厂
Edit Distance 1
无锡莹佳科技有限公司
无锡市莹佳科技有限公司
Edit Distance 1
湘潭市红楼实业有限公司锦绣红楼酒店
湘谭市红楼实业有限公司锦绣红楼酒店
Edit Distance 1
深圳市太立德仁文化传播有限公司
深圳太立德仁文化传播有限公司
Edit Distance 2
宁波甬达电梯有限公司
宁波博达电气有限公司
Edit Distance 2
交通银行抚顺分行河北支行抚东分理处
交通银行抚顺分行河北支行新城分理处
Edit Distance 2
丹阳市埤城镇胡桥卫生院
丹阳市埤城镇胡桥卫生院本部
Edit Distance 2
芜湖市永嘉制衣有限责任公司
芜湖市永嘉制衣有限公司
Edit Distance 2
交通银行抚顺分行河北支行新城分理处
交通银行抚顺分行河北支行抚东分理处
Edit Distance 2
重庆金凤丝绸集团有限公司
重庆金凤丝绸(集团)有限公司
Edit Distance 2
中国科学院广州地球化学研究所
中国科学院地球化学研究所
Edit Distance 2
费县探沂镇中心卫生院
费县探沂镇中心卫生院本部
Edit Distance 2
中国电信股份有限公司广东东莞高埗分公司
中国电信股份有限公司东莞高埗分公司
Edit Distance 2
潞城市翟店镇卫生院
潞城市翟店镇卫生院本部
Edit Distance 2
承德钢铁集团有限公司
承德钢铁股份有限公司
Edit Distance 2
包家乡卫生院本部
包家乡卫生院
Edit Distance 2
河北富华康土特环保有限公司
富华康土特环保有限公司
Edit Distance 2
中国科学院地球化学研究所
中国科学院广州地球化学研究所
Edit Distance 2
深圳艾捷科技有限责任公司
深圳艾捷科技有限公司
Edit Distance 2
大连工美企业有限责任公司
大连工美企业有限公司
Edit Distance 2
芜湖市永嘉制衣有限公司
芜湖市永嘉制衣有限责任公司
Edit Distance 2
中国科学院广州地球化学研究所
中国科学院地球化学研究所
Edit Distance 2
慈溪市坎墩街道社区卫生服务中心直塘村服务站
慈溪市坎墩街道社区卫生服务中心直塘村服务站本部
Edit Distance 2
慈溪市坎墩街道社区卫生服务中心直塘村服务站本部
慈溪市坎墩街道社区卫生服务中心直塘村服务站
Edit Distance 2
山东阳光体育设施有限公司
阳光体育设施有限公司
Edit Distance 2
中国银行青海省分行西宁市五四支行
中国银行青海省分行西宁市五四大街支行
Edit Distance 2
北京美大星巴克咖啡有限公司方庄贵友店
北京美大星巴克咖啡有限公司贵友店
Edit Distance 2
承德钢铁股份有限公司
承德钢铁集团有限公司
Edit Distance 2
大足县宝兴卫生院
大足县宝兴卫生院本部
Edit Distance 2
重庆金凤丝绸(集团)有限公司
重庆金凤丝绸集团有限公司
Edit Distance 2
平顺县龙溪镇卫生院本部
平顺县龙溪镇卫生院
Edit Distance 2
庆元县百山祖乡中心小学本部
庆元县百山祖乡中心小学
Edit Distance 2
竞业律师事务所
辽宁竞业律师事务所
Edit Distance 3
中国工商银行怀化市怀兴支行学院分理处
中国工商银行怀兴支行学院分理处
Edit Distance 3
宝山区邮政局
广水市邮政局
Edit Distance 3
广东省增城市华阳汽车换热器有限公司
增城市华阳汽车换热器有限公司
Edit Distance 3
北京市北华顺加油站有限责任公司
北京北华顺加油站有限公司
Edit Distance 3
中国农业银行甘肃省分行兰州市西固区支行福利路储蓄所
中国农业银行甘肃省分行兰州市西固区支行福利路分理处
Edit Distance 3
中国工商银行吉林省四平市分行铁东区平东支行
中国工商银行吉林省四平市分行平东支行
Edit Distance 3
中国科学院广州地化学研究所
中国科学院地球化学研究所
Edit Distance 3
包家乡卫生院
泉源卫生院
Edit Distance 3
郓城县仙纹染织有限公司
仙纹染织有限公司
Edit Distance 3
中国科学院广州地化学研究所
中国科学院地球化学研究所
Edit Distance 3
肇庆甘洒镇卫生院
怀集县甘洒镇卫生院
Edit Distance 3
淮安淮阴区新华书店
淮阴县新华书店
Edit Distance 3
中国工商银行吉林省四平市分行平东支行
中国工商银行吉林省四平市分行铁东区平东支行
Edit Distance 3
泉源卫生院
包家乡卫生院
Edit Distance 3
宁波市发展和改革委员会
浙江省宁波市发展和改革委员会
Edit Distance 3
中国农业银行湖南省株洲市分行炎陵县支行鹿原营业所
中国农业银行湖南省株洲市炎陵支行鹿原营业所
Edit Distance 3
和县历阳镇卫生院
歙县街口镇卫生院
Edit Distance 4
和县历阳镇卫生院
肇庆甘洒镇卫生院
Edit Distance 4
步阳集团
南京日报
Edit Distance 4
安溪县第三医院本部
如东县丁店医院本部
...
...
Edit Distance 4
丹阳市埤城镇胡桥卫生院本部
丹阳市蒋墅镇卫生院本部
Edit Distance 4
沈丘县邮电局
宝山区邮政局
Edit Distance 4
肇庆甘洒镇卫生院
歙县街口镇卫生院
Edit Distance 4
中国工商银行包头分行
宁德中国工商银行霞浦分行
Edit Distance 4
沈丘县邮电局
沾益县公安局
Edit Distance 4
费县探沂镇中心卫生院
博罗县石湾镇中心卫生院
Edit Distance 4
上海华联电器集团有限公司
浙江卓力电器集团有限公司
Edit Distance 4
三光科技有限公司
深圳艾捷科技有限公司
Edit Distance 4
费县探沂镇中心卫生院本部
燕矶镇中心卫生院本部
Edit Distance 4
程四酒家
步阳集团
Edit Distance 4
金坛市金城镇卫生院本部
德兴市银城卫生院本部
Edit Distance 4
仙纹染织有限公司
三光科技有限公司
Edit Distance 4
垣曲县蒲掌中心卫生院
昭觉县四开中心卫生院
Edit Distance 4
东莞德利信电子有限公司
东莞吉凯电器有限公司
Edit Distance 4
德兴市银城卫生院本部
金坛市金城镇卫生院本部
Edit Distance 4
金坛市金城镇卫生院本部
费县费城镇卫生院本部
Edit Distance 4
和县历阳镇卫生院
平顺县龙溪镇卫生院
Edit Distance 4
潞城市翟店镇卫生院本部
丰城市尚庄卫生院本部
Edit Distance 4
宁波博达电气有限公司
浙江九康电气有限公司
Edit Distance 4
广东省邮政公司揭阳市揭西县龙潭邮政支局
广东省邮政公司揭阳市惠来县葵潭邮政局
Edit Distance 4
汕头经济特区国际货运代理公司
汕头市国际货运代理公司
Edit Distance 4
东莞吉凯电器有限公司
东莞德利信电子有限公司
Edit Distance 4
青岛钢铁有限公司
承德钢铁股份有限公司
Edit Distance 4
衢州诚信汽车有限公司
苏州金信制衣有限公司
Edit Distance 4
程四酒家
南京日报
Edit Distance 4
昭觉县四开中心卫生院
垣曲县蒲掌中心卫生院
Edit Distance 4
无锡莹佳科技有限公司
三光科技有限公司
Edit Distance 4
青岛武晓集团有限公司
承德钢铁集团有限公司
Edit Distance 4
青岛钢铁有限公司
三光科技有限公司
Edit Distance 4
鹤壁供电公司
江西印刷公司
Edit Distance 4
城南拼线厂
南京日报
Edit Distance 4
南京日报
城南拼线厂
Edit Distance 4
三光科技有限公司
无锡莹佳科技有限公司
Edit Distance 4
广东省邮政公司揭阳市惠来县葵潭邮政局
广东省邮政公司揭阳市揭西县龙潭邮政支局
Edit Distance 4
和县历阳镇卫生院
怀集县甘洒镇卫生院
Edit Distance 4
苏州金信制衣有限公司
衢州诚信汽车有限公司
Edit Distance 4
浙江省烟草公司丽水市公司
河南省烟草公司新郑市公司
Edit Distance 4
江苏省范群干燥设备有限公司
江苏省范群干燥设备厂
Edit Distance 4
连州中医院
泉源卫生院
Edit Distance 4
九江酒厂有限公司
三光科技有限公司
Edit Distance 4
丰城市尚庄卫生院本部
德兴市银城卫生院本部
Edit Distance 4
青冈县第三医院
会宁县中医医院
Edit Distance 4
无锡莹佳科技有限公司
深圳艾捷科技有限公司
Edit Distance 4
博罗县石湾镇中心卫生院
费县探沂镇中心卫生院
Edit Distance 4
怀集县甘洒镇卫生院
歙县街口镇卫生院
Edit Distance 4
金鹰超市
程四酒家
Edit Distance 4
青岛钢铁有限公司
承德钢铁集团有限公司
Edit Distance 4
宝山区邮政局
沈丘县邮电局
Edit Distance 4
仙纹染织有限公司
九江酒厂有限公司
Edit Distance 4
浙江恒林椅业股份有限公司
浙江中达特钢股份有限公司
Edit Distance 4
平顺县龙溪镇卫生院
歙县街口镇卫生院
Edit Distance 4
乐山金口河区和平分社
金口河区和平小学
Edit Distance 4
广水市邮政局
沈丘县邮电局
Edit Distance 4
沾益县公安局
虹口公安分局
Edit Distance 4
沾益县公安局
沈丘县邮电局
Edit Distance 4
中国建设银行河北省唐山市分行缸窑路分理处
中国建设银行河北省唐山市分行缸窑支行
Edit Distance 4
苏州金信制衣有限公司
辽宁永兴制衣有限公司
Edit Distance 4
丹阳市蒋墅镇卫生院本部
丹阳市埤城镇胡桥卫生院本部
Edit Distance 4
安溪县第三医院本部
青冈县第三医院
Edit Distance 4
启东市海东中心卫生院(本部)
启东市海东中心卫生院
Edit Distance 4
南京金鹰国际集团
南京金鹰国际集团有限公司
Edit Distance 5
程四酒家
泉源卫生院
Edit Distance 5
教育部高教司
江西印刷公司
Edit Distance 5
九江酒厂有限公司
浙江九康电器有限公司
Edit Distance 5
程四酒家
北京四环宾馆
Edit Distance 5
肇庆甘洒镇卫生院
包家乡卫生院
Edit Distance 5
达州市精神病医院
宁波市康宁医院
Edit Distance 5
浙江九康电器有限公司
宁波博达电气有限公司
Edit Distance 5
交通银行温州分行车站大道支行
交通银行苏州分行张家港支行
Edit Distance 5
丰城市尚庄卫生院本部
大足县宝兴卫生院本部
Edit Distance 5
如东玉晟布业有限公司
龙南礼顿袜业有限公司
Edit Distance 5
安徽省古井集团有限责任公司
安徽古井酒店(集团)有限责任公司
Edit Distance 5
六五二职工医院
宁波市康宁医院
Edit Distance 5
歙县街口镇卫生院
大足县宝兴卫生院
Edit Distance 5
佛山市松川企业有限公司
河间市金桥铜业有限公司
Edit Distance 5
苏州金信制衣有限公司
明亮玻璃制品有限公司
Edit Distance 5
连州中医院
汕头市金砂中医院
Edit Distance 5
城南拼线厂
泉源卫生院
Edit Distance 5
古田县凤埔乡卫生院
大足县宝兴卫生院
Edit Distance 5
仙纹染织有限公司
威海艾迪姆有限公司
Edit Distance 5
河北省景县邮政局
宝山区邮政局
Edit Distance 5
德兴市银城卫生院本部
包家乡卫生院本部
Edit Distance 5
城南拼线厂
宏开木制品厂
Edit Distance 5
大足县智凤镇弥陀卫生院本部
大足县宝兴卫生院本部
Edit Distance 5
程四酒家
黑土地家常菜
Edit Distance 5
上海华联电器集团有限公司
上海马克电机阀门有限公司
Edit Distance 5
衢州诚信汽车有限公司
广州彩兴印刷有限公司
Edit Distance 5
无锡市莹佳科技有限公司
深圳艾捷科技有限公司
Edit Distance 5
宁波甬达电梯有限公司
东莞吉凯电器有限公司
Edit Distance 5
九江酒厂有限公司
内江隆昌农药有限公司
Edit Distance 5
南通市九色鹿业有限公司
辛集市鑫熙皮业有限公司
Edit Distance 5
金鹰超市
世纪杂志社
Edit Distance 5
城南拼线厂
程四酒家
Edit Distance 5
浙江九康电器有限公司
九江酒厂有限公司
Edit Distance 5
包家乡卫生院本部
费县费城镇卫生院本部
Edit Distance 5
北京美大星巴克咖啡有限公司天津开发区名都咖啡店
北京星巴克咖啡有限公司天津名都咖啡店
...
结果集下载:http://orfuc602j.bkt.clouddn.com/data-sets/repeat/part-00000
可以看到当 edit distance 比较 ( >4 )的时候数据处理的质量已经不能保证,因此需要从其他方面解决。
未解决的问题和新的挑战:
1. 默认的 Edit Distance 算法没法解决中文分词问题
2. 同义词/近义词/中英文 相关的问题未考虑
3. 目前只进行了 1 :1 的比较,应该实现 1 对多的比较
除了去重,该方法也适用于数据关联,不同表之间进行数据关联,同理也是用 Edit Distance ,改进方法也如上,同时可以加入更多字段进行处理。
提供两个测试数据集合: