• Matlab 实现对码功能


    1、什么叫对码?

    举例说明,数据库中有两张表。

    表 1:

    编号 描述
    
    11 儿科门诊
    
    22 妇科门诊
    
    33 产科门诊

    表 2:

    编号 描述
    
    111 儿科门诊
    
    222 妇科门诊
    
    333 产科门诊

    现在要在表 1 和表 2 之间找到一一对应。比如:

    编号1 编号2
    
    11 111
    
    22 222
    
    33 333

    这就是对码。

    是不是很简单?只要 select 出两个表中描述相同的编号就可以了。但如果两个表的描述并不是那么准确相等呢?譬如一个是「产科」,一个是「妇产科」,怎么找到匹配呢?有人会说用 like '%产科%' 模糊匹配,用存储过程也能实现,但你怎么知道哪个表的描述内容少呢,该 like 哪个表字段呢?还有,如果一个是「妇科」,一个是「妇产科」呢?这个想当然地用 like 肯定是不行了。这个时候就要找个方法来计算两个字符串的相似度或者匹配度,选择相似度最高的数据来做匹配。

    对码这种需求其实是很常见的。比如,现有运行的系统里用的是表 1,现在上级部门要求你给它定期传数据,而且要求科室编号用表 2,一般情况下不可能直接在自己运行良好的系统里贸然用表 2 替换表 1,只有新建个表 1 和表 2 的对码表,在提取的时候对表 1 的编号做个替换。而且经常表 1 和表 2 的描述还不完全相同,这个对码就是个问题。

    对码可以手工对,用自己的眼睛一个一个找,那么当数据量很大时,这将是场灾难。所以,正常点儿的工程师都会写程序先实现初级的字符串匹配,然后再人工检查,纠正程序处理不了的错误。

    本文介绍的就是如何利用字符串相似度的知识来做这个对码。

    2、对码,有很多方法可以实现。比如我相信一些对 SQL 高手可以轻松用存储过程实现。我这里是先把表 1 和表 2 读取到文本里,然后用 Matlab 读取并做匹配,再将匹配结果写入到新文本里。当然,这个用 Python、R 语言也可以轻松实现,很简单。我这里选择 Matlab 只是因为自己最近用得多点儿。

    文本1:HIS.txt 

    992    心血管儿科
    993    血液儿科
    994    新生儿科
    995    感染儿科
    996    妇科门诊
    997    产科门诊

    文本2:YY.txt

    1008    生殖医学中心IVF
    1307    妇科化疗
    1036    妇科ICU
    1004    产科
    1303    妇科
    1302    妇产科门诊
    1030    妇产科教研室
    1093    妇产科

    Matlab 代码如下:

    [YYcode,YYdesc]=textread('YY.txt','%s%s');
    yylen=length(YYcode);
    [hiscode,hisdesc]=textread('HIS.txt','%s%s');
    hislen=length(hiscode);
    HISyy=cell(1,4);
    HISyy{1}=hiscode;
    HISyy{2}=hisdesc;
    for i=1:1:hislen
    index=1;
    simMax=0;
    for j=1:1:yylen
    simValue=levenshtein(hisdesc{i},yydesc{j});
    if simValue>simMax
    simMax=simValue;
    index=j;
    end
    end
    HISyy{3}{i}=YYcode{index};
    HISyy{4}{i}=YYdesc{index};
    end
    
    fp = fopen('HIS-yy.txt','wt');
    for i=1:1:hislen
    fprintf(fp,'%s	',HISyy{1}{i});
    fprintf(fp,'%s	',HISyy{2}{i});
    fprintf(fp,'%s	',HISyy{3}{i});
    fprintf(fp,'%s
    ',HISyy{4}{i});
    end
    fclose(fp);

    其中 levenshtein 函数是计算两个字符串的相似度,用的是「最小编辑距离」。

    levenshtein.m。该代码来自网络:http://download.csdn.net/detail/zc0928/4783710

    function re=levenshtein(ch1,ch2)
    n=length(ch1);
    m=length(ch2);
    if n==0
        LD=m;
    end;
    if m==0
        LD=n;
    end;
    A=zeros(n+1,m+1);
    for ii=1:n+1
    A(ii,1)=ii-1;
    end;
    for ii=1:m+1;
    A(1,ii)=ii-1;
    end;
    for ii=2:m+1
    for j=2:n+1
    if ch2(ii-1)==ch1(j-1)
    cost=0;
    else cost=1;
    end;
    a=A(j-1,ii)+1;
    b=A(j,ii-1)+1;
    c=A(j-1,ii-1)+cost;
    d=min(a,b);
    A(j,ii)=min(c,d);
    end;
    end;
    LD=A(n+1,m+1);
    re = (max(n,m) - LD)/max(n,m);
    View Code

    生成的对码文件:HIS-yy.txt

    990    普儿一区    1407    普儿一科
    991    普儿二区    1048    普儿二科
    992    心血管儿科    1405    心血管科
    993    血液儿科    1046    新生儿科
    994    新生儿科    1406    新生儿科
    995    感染儿科    3046    感染管理科

    3、Matlab 处理流程

    首先读取两个表的文本,并计算数据个数。

    [YYcode,YYdesc]=textread('YY.txt','%s%s');
    yylen=length(YYcode);
    [hiscode,hisdesc]=textread('HIS.txt','%s%s');
    hislen=length(hiscode);

    然后创建元胞数组,并把第一个文件的值复制进去。注意元胞数组的使用,这里创建了 1 行 4 列的元胞数组,每个元素又可以存储任意个字符串数组,每个元素的类型跟上面的 YYcode 和 YYdesc 一样。

    HISyy=cell(1,4);
    HISyy{1}=hiscode;
    HISyy{2}=hisdesc;

    接下来遍历第一个文件中的每一个描述,将该描述字符串同第二个文本中的每一个描述做匹配,计算相似度,最终取得相似度最高的存到元胞数组的第三列和第四列。

    for i=1:1:hislen
    index=1;
    simMax=0;
    for j=1:1:yylen
    simValue=levenshtein(hisdesc{i},yydesc{j});
    if simValue>simMax
    simMax=simValue;
    index=j;
    end
    end
    HISyy{3}{i}=YYcode{index};
    HISyy{4}{i}=YYdesc{index};
    end

    最后将 HISyy中的结果写入文件 HIS-yy.txt。

    fp = fopen('HIS-yy.txt','wt');
    for i=1:1:hislen
    fprintf(fp,'%s	',HISyy{1}{i});
    fprintf(fp,'%s	',HISyy{2}{i});
    fprintf(fp,'%s	',HISyy{3}{i});
    fprintf(fp,'%s
    ',HISyy{4}{i});
    end
    fclose(fp);

     

  • 相关阅读:
    set bootarges
    UI 中的 结构体 字符串的 初始化
    putchar 代替printf
    石家庄 工作
    What's the value of i++ + i++?
    printf 打印 指定长度 字符串
    UI 点滴 积累
    static 关键字
    sdk
    隐式类型转换
  • 原文地址:https://www.cnblogs.com/NaughtyBaby/p/4972678.html
Copyright © 2020-2023  润新知