背景:在预处理的过程中,要将基础疾病按照ICD-10的标准,对应转换成代码,数据量大概1000~1500,尝试利用R语言进行匹配。
遇到的问题:基础疾病选用的是医生的诊断,不规范的写法导致匹配困难。
尝试解决一:python的批量匹配,用的是jieba库,但是匹配效果不好,可以说很差,不知道哪里的问题,刚开始摸索python,后续待解决。
from gensim import corpora, similarities, models
import jieba
import pandas as pd
find = pd.read_csv("2.1.csv") ###基础疾病
data = pd.read_csv("6.1.csv") ###ICD-10
data_split_word = data.diease.apply(list)
dictionary = corpora.Dictionary(data_split_word.values)
data_corpus = data_split_word.apply(dictionary.doc2bow)
find_split_word = find.V1.apply(list)
dictionary2 = corpora.Dictionary(find_split_word.values)
find_corpus = find_split_word.apply(dictionary2.doc2bow)
tfidf = models.TfidfModel(data_corpus.to_list())
index = similarities.SparseMatrixSimilarity(
tfidf[data_corpus], num_features=len(dictionary))
result = []
for corpus in find_corpus.values:
sim = pd.Series(index[corpus])
result.append(data.diease[sim.nlargest(3).index].values)
result = pd.DataFrame(result)
print(result)
result.rename(columns=lambda i: f"匹配{i+1}", inplace=True)
result = pd.concat([find, result], axis=1)
参考的方法见:批量模糊匹配的三种方法_小小明-代码实体的博客-CSDN博客_批量模糊匹配
后来将jieba.lcut改成list(),效果也不好,日后有空再琢磨。
尝试解决二:利用R的stringdist包,目前正在尝试,也许效果不错。
找匹配的最相似的前三项,顺便将对应的ICD代码附在后面,程序很穷举,耗时很长,不要求了。
(跑之前在excel里给待选排个序;记得算数量时不要计算空行)
library(readr)
library(stringdist)
X <- read.csv("2.csv",header=T)
SIX <- read.csv("6.1.csv",header=T)
SIX<-SIX[-1,]
Y<-matrix(nrow=1083,ncol=9)
{
t1=proc.time()
for(i in 1:1083){
print(i)
s=1000;m=1000;n=1000;q=1000
for(j in 1:22543){
Y[i,1]<-X[i,2]
t<-stringdist(X[i,2], SIX[j,2],method = "jaccard")
if(t==0){q<-t
Y[i,2]<-SIX[j,2]
Y[i,3]<-SIX[j,1]
Y[i,4:9]<-NA
break
}
else if(t<=s){
if(t<=m){
if(t<=n){
if(t<=q){
q<-t
n<-q
Y[i,3]<-Y[i,2]
Y[i,7]<-Y[i,6]
Y[i,2]<-SIX[j,2]
Y[i,6]<-SIX[j,1]
}
else{n<-t
m<-n
Y[i,4]<-Y[i,3]
Y[i,8]<-Y[i,7]
Y[i,3]<-SIX[j,2]
Y[i,7]<-SIX[j,1]}
}
else{m<-t
s<-m
Y[i,5]<-Y[i,4]
Y[i,9]<-Y[i,8]
Y[i,4]<-SIX[j,2]
Y[i,8]<-SIX[j,1]}
}
else{s<-t
Y[i,5]<-SIX[j,2]
Y[i,9]<-SIX[j,1]}
}
}
}
t2=proc.time()
t=t2-t1
print(paste0('执行时间:',t[3][[1]],'秒'))
}
Y<-cbind(X[1:1083,1],Y)
write.csv( Y , "A.csv")
改了一个地方:距离小的往前放,本来在前面的往后排。
加了一个地方:在距离为0的时候,直接跳出循环,只保留最接近的选项。
最后出来的效果不错,对于短文本来说,这个的效果应该是在力求保证正确率的程序里相对较好的,至少我已经满意了。
过程中试了两个距离计算方法,一个jaccard,一个cosine,jaccard不考虑词频,cosine考虑词频。对于基础疾病来讲,jaccard的效果会好一点。
后续还需要人工进行比较,在四个候选选项里挑一个最接近的,也另有四个候选里没有正确选项的,需要自行改正,比如“冠心病”,标准写法是“冠状动脉性心脏病”,但是机器来比较几乎不可能选到正确的。(烦)