Python格式化解析不规则txt文本并转为dataframe

很多时候我们拿到的文本文件都是格式不规范的,甚至是相当不规范的。。所以我们想要把不规范的文本文件变成规范的表格式,便于后续的模型训练和分析,在本篇文章中,主要的难点是从文本文件提取key-value的工作。

Step-0:数据示例

比如我们需要把如下数据中的key和value分别提取出来,并将相同key的值放在一列:

qid=157238221 isAdopted=1 qTags= qTime=2010-06-03 19:47 giveScore=200 askerid=188349317 askerGrade=5 askerGoodRate=48 askerAnswerNumber=44 askerName=cribberbd aid=467956656 isBest=1 ahasComment=0 aTime=2010-06-04 16:54 aCon=参看:a href="http:baike.baidu.comview1678662.htm?fr=ala0_1_1" target="_blank"http:baike.baidu.comview1678662.htm?fr=ala0_1_1a answerid=169837710 answerName= answerCareField= answerGrade= answerGoodRate= answerNum= answerIsMaster= answerIsFamous= aid=467569408 isBest= ahasComment=0 aTime=2010-06-03 20:09 aCon= will always love you下载地址a href="http:mp3.baidu.comm?f=ms&rn=&tn=baidump3&ct=134217728&word=I+will+always+love+you&lm=-1" target="_blank"http:mp3.baidu.comm?f=ms&rn=&tn=baidump3&ct=134217728&word=I+will+always+love+you&lm=-1a answerid=129235439 answerName=唯念潇湘 answerCareField= answerGrade=5 answerGoodRate=40 answerNum=46 answerIsMaster=0 answerIsFamous=0 aid=467584335 isBest= ahasComment=0 aTime=2010-06-03 20:35 aCon=是i will always love you= = answerid=12422236 answerName=qizi86 answerCareField=电视" answerGrade=18 answerGoodRate=36 answerNum=13266 answerIsMaster=0 answerIsFamous=0 aid=467849272 isBest= ahasComment=0 aTime=2010-06-04 13:17 aCon=长风镖局》 answerid=194560318 answerName=水滴里的火花 answerCareField= answerGrade=2 answerGoodRate=19 answerNum=5 answerIsMaster=0 answerIsFamous=0 aid=470025197 isBest= ahasComment=0 aTime=2010-06-08 17:27 aCon=长风镖局》 answerid=192636431 answerName=346317740 answerCareField=校园生活 answerGrade=5 answerGoodRate=14 answerNum=17 answerIsMaster=0 answerIsFamous=0

Step-1:数据载入:

没什么可说的,直接with open,需要注意的是原始文档当中有特殊字符,因此需要加上忽略错误with open(filename,encoding='utf-8',errors='ignore') as f:

另外由于原始文件特别大,为了避免内存直接爆掉,采用了循环逐行读取的f.readline()。

Step-2:格式化:

进入重头戏格式化,分析数据发现不同的keyvalue对是用空格分割的,但是许多内容中本身就有空格。。。坑爹啊这不是。。。看来直接用空格分割不靠谱。。。

后来尝试了分割成list,用list组成dataframe,不过分完才发现,每条记录的key个数并不相同,所以这样做也会出问题。

最后发现key、value之间是用=号分割的,因此采用正则来提取pattern,但是提取出来才发现,许多文本中也含有“=”这个特殊字符,做到这我已经想不出别的招来了= =,所以决定给“=”前后正则加上限制,只有大小写英文小写开头小写结束(分析不完整的参数key字典发现的规则)的才勉强算是正常的key,后面通过key传非空的比例来决定key的取舍,异常的key的值空率放在大样本上应该是接近百分百的。。

最后话不多说,放代码吧:

def load_data(filename,n):

    with open(filename,encoding='utf-8',errors='ignore') as f:

    #f=open('QACorpusData',encoding='utf-8',errors='ignore')

        #确定正则匹配模式

        pattern= re.compile(r'[a-z]{1,}[a-zA-Z]{1,}[a-z]{1,}=[^=]{0,} |[a-z]{1,}[a-zA-Z]{1,}[a-z]{1,}=[^=]{0,}')

        #循环文件中每一行

        kv_data_Q=[]

        kv_data_A=[]

        #for each_line in f:

        for k in range(0,n):

            #将Question和Answer分开分别建表

            each_line= f.readline()

            line=each_line.strip().split('\t')

            for i in range(0,len(line)):

                ss=pattern.findall(line[i])

                #print(ss)

                #print(len(ss))

                data=[]

                #取出key-value并分割

                for i in ss:

                    tmp=i.strip().split('=')

                    data.append(tmp)

                #转换为dict类型

                data_dict=dict(data)

                #增加Q&A分类

                if 'qid' in data_dict.keys():

                    #data_dict['type']='Q'

                    qid=data_dict['qid']

                    #append到Qusetion表

                    kv_data_Q.append(data_dict)

                else:

                    data_dict['qid']=qid

                    #data_dict['type']='A'

                    kv_data_A.append(data_dict)

                    #append到Answer表

        df_Q=pd.DataFrame.from_dict(kv_data_Q)

        df_A=pd.DataFrame.from_dict(kv_data_A)

        return df_Q,df_A

    #f.close()

Step-3:去除误识别:

通过列的空值比例去除误识别,代码如下:

#考察各列的空值个数

def empty_count(df):

    n=len(df)#数据集记录数

    empty_cnt = pd.DataFrame(columns=['columns_name', 'normal', 'null','empty'])

    for c in df.columns:

        n_cnt=sum(df[c].isnull())#判断是否为NaN

        e_cnt=sum(df[c].apply(lambda x: True if x ==''  else False))#判断是否为空字符

        empty_cnt=empty_cnt.append({'columns_name':c,'normal':(n-n_cnt-e_cnt)/n,'null':n_cnt/n,'empty':e_cnt/n},ignore_index=True)

    return empty_cnt

    #print(empty_cnt)

#删除异常的列   

def del_cols(df):

    df_ec=empty_count(df)

    for col in df_ec[df_ec.null>=0.9].columns_name:

        df.drop(col,axis=1,inplace=True)

for df_deal in [df_Q_Cheat,df_A_Cheat,df_Q_Normal,df_A_Normal]:

    del_cols(df_deal)

    print(df_deal,'check!')


Python格式化解析不规则txt文本并转为dataframe_第1张图片
空值判断效果

你可能感兴趣的:(Python格式化解析不规则txt文本并转为dataframe)