接到一个述求,想把txt里面的药品说明书转换成csv格式,对应药品的属性为列名,属性的介绍作为values。分成两种方式实现,当然原数据是不一样的。
1.一个TXT文件中含有多个商品
原数据:
保存后的CSV格式数据:
直接上代码:
# -*- coding:utf-8 -*-
import pandas as pd
import re
import numpy as np
import os
import glob
from itertools import chain #展平列表
import numpy as np
from tqdm import tqdm
pd.set_option('display.max_columns', None) #设置显示总行数
def split_item(df):
#分块商品,返回商品索引
datas = list(chain.from_iterable(df.values.tolist()))
items_index = []
for i,data in enumerate(datas):
if data.find("个商品:") != -1:
items_index.append(i)
return items_index,datas
def lambda_name(x):
#获取药品属性
if "【" in x:
return str(x)[:str(x).find("】")].replace("【","")
def huanhang(it):
#处理换行数据
new_it = []
#统计【开始的位置,去除最后一列
str_dt = "".join(it[:-1])
index = [i.start() for i in re.finditer('【', str_dt)]
for i in range(len(index)):
if i+1 < len(index):
new_it.append(str_dt[index[i]:index[i+1]])
else:
new_it.append(str_dt[index[i]:])
new_it.append("【病情描述】"+it[-1])
return new_it
data_path = glob.glob("*txt")
#pf = max_columns_dataframe(data_path)
pf = pd.DataFrame([{"药品名称":np.nan}])
pf = pf.dropna()
#添加数据
for n,file in enumerate(data_path):
#df = pd.read_csv(file,encoding="gbk",names=['items']) #读取含中括号时数据缺失
df = pd.read_table(file,encoding="gbk",names=['items']) #正常读取
#columns = df[df.columns.tolist()[0]].apply(lambda x:str(x)[:str(x).find("】")].replace("【","")) #此处代码中存在一定缺陷,由于原数据中必须带有【】,负责查找不出来
items_index,datas = split_item(df) #返回商品索引
data_bar = tqdm(list(range(len(items_index))))
for index in data_bar:
if index+1<len(items_index):
if index==2448:
print(131231231)
it = datas[items_index[index]+1:items_index[index+1]]
#换行数据处理
it = huanhang(it)
ddf = pd.DataFrame([it]).T #单个药品说明书
ddf.columns = [datas[items_index[index]]]
columns = ddf[ddf.columns.tolist()[0]].apply(lambda x:lambda_name(x))
columns = columns.dropna()
columns_name = columns.values.tolist()
it_index = re.findall("\d+", ddf.columns.tolist()[0], flags=0)[0] #获取商品ID
data_bar.set_description(f'总共有{len(data_path)}个文件,正在处理{n+1}/{len(data_path)},{file}文件中第{index}个商品,商品id为{it_index}')
dicts = dict.fromkeys(columns_name)
tf = pd.DataFrame([dicts],index=[it_index]) #创建新datafrom
for i,j in zip(columns_name,ddf.values.tolist()):
if j[0].find(i) != -1:
if "】" in j[0]:
tf[i] = j[0].split(f"【{i}】")[-1]
else:
tf[i] = np.nan
pf = pd.concat([pf,tf])
pf.sort_index(inplace=True) #根据索引排序
pf.to_csv("药品说明书预处理.csv")
2 .每个TXT文件对应一个商品
原数据:
保存后的CSV格式数据:
源码:
# -*- coding:utf-8 -*-
import pandas as pd
import re
import numpy as np
import os
import glob
pd.set_option('display.max_columns', None) #设置显示总行数
def lambda_name(x): #获取药品属性
if "【" in x:
return str(x)[:str(x).find("】")].replace("【","")
else:
#给说明书中没有【】的加上【】
name = list(x[:x.find(":")].strip())
name.append("】")
name.append(x[x.find(":"):])
name.insert(0,"【")
x = "".join(name)
return str(x)[:str(x).find("】")].replace("【","")
def max_columns_dataframe(data_path):
#返回药品说明书中最多的列
num = []
for i,path in enumerate(data_path): #
df = pd.read_csv(path,encoding="utf-8")
columns = df[df.columns.tolist()[0]].apply(lambda x:lambda_name(x))
num.append(len(columns))
file = data_path[num.index(max(num))] #找出列明最多的文件
df = pd.read_csv(file,encoding="utf-8")
columns = df[df.columns.tolist()[0]].apply(lambda x:lambda_name(x))
columns_name = columns.values.tolist()
index = re.findall("\d", df.columns.tolist()[0], flags=0)[0] #获取商品ID
dicts = dict.fromkeys(columns_name)
pf = pd.DataFrame([dicts],index=[index]) #创建新datafrom
return pf.dropna()
data_path = glob.glob("*txt")
pf = max_columns_dataframe(data_path)
#添加数据
for file in data_path:
df = pd.read_csv(file,encoding="utf-8")
#columns = df[df.columns.tolist()[0]].apply(lambda x:str(x)[:str(x).find("】")].replace("【","")) #此处代码中存在一定缺陷,由于原数据中必须带有【】,负责查找不出来
columns = df[df.columns.tolist()[0]].apply(lambda x:lambda_name(x))
columns_name = columns.values.tolist()
index = re.findall("\d", df.columns.tolist()[0], flags=0)[0] #获取商品ID
dicts = dict.fromkeys(columns_name)
tf = pd.DataFrame([dicts],index=[index]) #创建新datafrom
for i,j in zip(columns_name,df.values.tolist()):
if j[0].find(i) != -1:
if "】" in j[0]:
tf[i] = j[0].split("】")[-1]
else:
tf[i] = j[0].split(":")[-1]
else:
tf[i] = np.nan
pf = pd.concat([pf,tf])
pf.sort_index(inplace=True) #根据索引排序
pf.to_csv("药品说明书预处理.csv")
遇到的问题总结:
1.有的药品说明书中没有【】号,因此在代码中加上【】,但是还存在缺陷,最好的是在爬虫的时候,将爬取的数据做一定的处理。
2.在多个商品在一个文件中,采用先将文件中的商品数的位置找出来,然后采用字符串的索引进行分块数据。
3.在成分一列中,存在换行,而pandas中读取的数据都是每一行,因此将数据中的换行先list成一句话,在进行处理。最好的方法是在爬虫的过程中进行处理。
4.使用pandas中读取 pd.read_csv(file,encoding=“gbk”,names=[‘items’]) 和pd.read_table(file,encoding=“gbk”,names=[‘items’]) ,前者在读取的数据中有[]时,读取的数据缺失,采用pd.read_table可以进行正常读取。