对非结构化数据进行结构化处理 保姆级教程+总结——2021泰迪杯挑战赛—B题任务4

对非结构化数据进行结构化处理 保姆级教程+总结——2021泰迪杯挑战赛—B题任务4,第1张

对非结构化数据进行结构化处理 保姆级教程+总结——2021泰迪杯挑战赛—B题任务4

叨叨(σ゚∀゚)σ:
好久没做Python数据分析了,感觉自己什么都不会= = ;
一天做了一题也是没谁了…55555(T▽T)还好队友靠谱。。。。。
主要是正则表达式有点晕乎(没有接触过惭愧),花了非常多时间。

本篇适合Python小白学(以后也可以留给自己看hhh)
大佬们可以直接跳到最终代码区
欢迎讨论批评指正━(`∀´)ノ亻!

仅供学习参考呀~侵删

文章目录
  • 从jupyter notebook开始
  • Pandas入门学习
  • 题目描述:任务 4 肥料产品的多维度对比分析
    • 任务 4.1
    • 任务 4.2
    • 数据说明
  • 数据常用方法
    • 常用导入数据方法
    • 查看数据常用方法
    • 导出数据
  • 正则表达式
  • Python正则表达式匹配: re.match
  • 4-1代码
  • 4-2代码
  • 关于Pandas的contains和extract

从jupyter notebook开始

1、下载
anaconda里面直接下(前提是需要安装了Python(3.3版本及以上,或2.7版本)
从环境开始的,看大佬的Anaconda介绍、安装及使用教程

2、安装
从jupyter notebook安装开始的,还是大佬的:Jupyter Notebook介绍、安装及使用教程

3、打开jupyter

1)win+ R 打开运行
2)输入jupyter notebook
3)复制链接到浏览器打开即可

4、熟悉jupyter快捷键
Shift-Enter : 运行本单元,选中下个单元
Ctrl-Enter : 运行本单元
Alt-Enter : 运行本单元,在其下插入新单元
D,D : 删除选中的单元
 
 

Pandas入门学习

官方文档:10 minustes to pandas
这个超好用hhh: Pandas速查链接
 
 

 
 

题目描述:任务 4 肥料产品的多维度对比分析 任务 4.1

设计算法或处理流程,从附件 4 技术指标中提取出氮、磷、钾养
分和有机质的百分比,以及肥料含氯的程度。请在报告中给出处理思路及过程,
并将结果保存到文件“result4_1.xlsx”中。

注:如果技术指标中只给出总养分百分比(“≥”按照“=”处理)而无明细数据,
则氮、磷、钾养分的百分比按照总百分比的 1/3 来计算,结果保留 3 位小数(例如 1.0%,即 0.010)。
复混肥料属于无机肥料,它的有机质百分比设定为 0。
含氯情况分为“无氯”、“低氯”、“中氯”和“高氯”4 种。如果肥料产品的技术指标中没有给出含氯情况,
则视为“无氯”;如果注明“含氯”,则视为“低氯”。
任务 4.2

设计算法或处理流程,从附件 4 原料与百分比中提取各种原料的
名称及其百分比。请在报告中给出处理思路及过程,并将结果保存到文件
“result4_2.xlsx”中(参见表 2)。

数据说明

附件 4 给出了某省肥料登记数据中营养成分及原料构成的原始数据。

      字段技术指标以字符串的形式给出了肥料的营养成分的百分比。例如某复混肥料的技术指标字段取值为“N+P2O5+K2O≥20%(7-10-3) 有机质≥20% 含氯”,表示肥料中氮磷钾三大元素的总养分含量不小于 20%;“(7-10-3)”指的是氮磷钾的配比,氮含量为 7%,磷肥成分(折算为 P2O5)含量为 10%,钾肥成分(折算为K2O)含量为 3%;“有机质≥20%”表示肥料中有机质的含量不小于 20%;

      “含氯”表示肥料中含有氯元素。有机肥料由于不含无机养分或含量较少,有些产品只在技术指标中标明“总养分≥…%”,没有给出氮、磷、钾 3 大元素的具体含量。

      字段原料与百分比以字符串的形式给出了肥料的原料构成及质量百分比,例如某有机肥料的原料与百分比字段取值为“糖蜜酒精废液 (占 25%),发酵菌种(占 1%),木糠 (占 25%),滤泥 (占 49%)”,表明了该有机肥料由蜜糖酒精废液、发酵菌种、木糠和滤泥四种原料构成,质量百分比分别是 25%、1%、25%及 49%。

  
  
 
  
  
 

数据常用方法 常用导入数据方法

pd.read_csv(filename):从CSV文件导入数据
pd.read_table(filename):从限定分隔符的文本文件导入数据
pd.read_excel(filename):从Excel文件导入数据
 

查看数据常用方法

df.head(n):查看Dataframe对象的前n行
df.tail(n):查看Dataframe对象的最后n行
df.shape():查看行数和列数
 

导出数据
data4.to_excel(r"C:Users感谢看到这里Desktopresult4_1.xlsx")

 

 
 

 
先导入基础模块啦

#一些基础模块
import numpy as pnp
import matplotlib.pyplot as plt
import pandas as pd

#导入Python模块re后面会用
import re

导入数据

data4=pd.read_excel("附件4.xlsx",encoding='gbk')#载入数据
data4.head()#观察一下

篇幅有限这里只展示了几种情况:

以我只有一次处理这种数据的经验(hhhh)观察数据看一百行左右,心理有个底( *** 作熟练的同学可以通过关键字筛选进行观察,更加清晰),这里总数据量只有两百行所以人眼也很快。

仔细观察‘技术指标’的几个维度:

1、氮磷钾的成分比
(决定因素2个:1、优先有具体配比的;2、总养(氧)分以及(N+P2…)后面的总数;)

2、含氯情况
(决定因素2个:1、优先有小括号的具体含氯情况;2、无括号的情况(含氯、其他);)

3、有机质含量
(数据一定在‘’有’字后面(有可能打错字但是‘’有‘’字都没错),复合肥料=0)

好的,到这里应该意识到是用正则表达式进行筛选,而且在官方的题目pdf中也说明了这是非结构化数据,不能用简单的关键字进行匹配。
(看过原数据的人都知道,想要关键字匹配不可能)

下面有请我们的重磅嘉宾:正则表达式!!!
 
  
  
 
 

正则表达式

没学过的人可能都像我一样,觉得有点像读天书 ⊙︿⊙。。。
但是不要害怕,它其实是一个数据格式的表示。
本题不需要很难的语法,所以入门知道几个常用的以及会查自己想要的即可。

正则表达式在线工具——菜鸟教程(主要是看它下面的常用表达式)
正则表达式 - 语法_菜鸟教程

1、氮磷钾的成分比
(决定因素2个:1、优先有具体配比的;2、总养(氧)分以及(N+P2…)后面的总数;)

pattern1=r'(d{1,2})―(d{1,2})―(d{1,2})'#这是中间是中文字符的横杠‘’―‘’
pattern2=r'(d{1,2})-(d{1,2})-(d{1,2})'“#这是中间是英文字符的横杠‘’-‘’
    
pattern3=r'总[养,氧]分(.*?)≥(([1-9][0-9]*)+(.[0-9]{1,2})?)'
pattern4=r'N(.*?)≥(([1-9][0-9]*)+(.[0-9]{1,2})?)'

2、含氯情况
(决定因素2个:1、优先有小括号的具体含氯情况;2、无括号的情况(含氯、其他);)

pattern1=r'([u4e00-u9fa5]氯)'
pattern2=r'[u4e00-u9fa5]氯|[u4e00-u9fa5]s氯'

3、有机质含量
(数据一定在‘’有’字后面(有可能打错字但是‘’有‘’字都没错),复合肥料=0)

  pattern1=r'有(.*?)≥(([1-9][0-9]*)+(.[0-9]{1,2})?)'

好了抓住了蛇的七寸,还需要一块石头它就能over了(本篇没有虐待任何动物)( ̄▽ ̄)/

  
  
   
  
 

Python正则表达式匹配: re.match

非常简单易懂的教程:
Python 正则表达式_菜鸟教程

学成归来:
自己可以先测试一下效果哈
比如含氯情况的:

test1='总养分(N+P2O5+K2O)≥43% (10―18―15)含氯(低氯) TT型'
pattern1=r'([u4e00-u9fa5]s氯)|([u4e00-u9fa5]氯)'
matchObj=re.search(pattern1,test1)
a = str(matchObj)
print(matchObj)
print(a)

结果是:



  
 

再进行一次提取,去掉括号:
(这里也可以直接切片了,但是嘛我脑子当时可能瓦特了)

matchObj3=re.search(r'[u4e00-u9fa5]氯',a)
b = str(matchObj3)

结果是:

我们要的最终结果只有含氯的词,所以通过字符串索引进行切片即可。

b[-4:-2] = '低氯'

到了这里已经完成核心的方法,剩下的就是封装一个函数把整理好的数据放进表格里。

  
  
   
  
 

4-1代码

氮磷钾百分比:

def percentageNPK(data):
    pattern1=r'(d{1,2})―(d{1,2})―(d{1,2})'
    pattern2=r'(d{1,2})-(d{1,2})-(d{1,2})'
    pattern3=r'总[养,氧]分(.*?)≥(([1-9][0-9]*)+(.[0-9]{1,2})?)'
    pattern4=r'N(.*?)≥(([1-9][0-9]*)+(.[0-9]{1,2})?)'
    list = []
    i = 0
    for i in range(len(data.index)):
        matchObj1=re.search(pattern1,str(data['技术指标'][i]))
        matchObj2=re.search(pattern2,str(data['技术指标'][i]))
        matchObj3=re.search(pattern3,str(data['技术指标'][i]))
        matchObj4=re.search(pattern4,str(data['技术指标'][i]))
        
        if matchObj1 != None:#
            a = str(matchObj1.group(1))
            b = str(matchObj1.group(2))
            c = str(matchObj1.group(3))
            tmp = a+'%'+' '+b+'%'+' '+c+'%'
            list.append(tmp)
        elif matchObj2 != None:#
            a = str(matchObj2.group(1))
            b = str(matchObj2.group(2))
            c = str(matchObj2.group(3))
            tmp = a+'%'+' '+b+'%'+' '+c+'%'
            list.append(tmp)
            
        elif matchObj3 != None:#
            a = matchObj3.group(2)
            tmp1=str(round(float(a)/3,3))#保留3位小数
            tmp = tmp1+'%'+' '+tmp1+'%'+' '+tmp1+'%'+' '
            
            list.append(tmp)
            
        elif matchObj4 != None:#
            a = matchObj4.group(2)
            tmp1=str(round(float(a)/3,3))#保留3位小数
            tmp = tmp1+'%'+' '+tmp1+'%'+' '+tmp1+'%'+' '
            list.append(tmp)
        
        else:
            list.append('none')
            
    data.insert(1,"氮、磷、钾养分的百分比",list)
    return data


data4 = percentageNPK(data4)


含氯情况:

def cl(data):
    pattern1=r'([u4e00-u9fa5]氯)'
    pattern2=r'[u4e00-u9fa5]氯|[u4e00-u9fa5]s氯'
    list = []
    i = 0
    for i in range(len(data.index)):
        matchObj1=re.search(pattern1,str(data['技术指标'][i]))
        matchObj2=re.search(pattern2,str(data['技术指标'][i]))
        
        if matchObj1 != None:#先判断有小括号的
            a = str(matchObj1)
            matchObj3=re.search(r'[u4e00-u9fa5]氯',a)
            b = str(matchObj3)
            list.append(b[-4:-2])
            
        elif matchObj1 == None and matchObj2 != None:#在判断无小括号的
            b = str(matchObj2)
            
            if '含氯'in b or '含 氯'in b:
                list.append('低氯') #若只出现了‘含氯’,则视为低氯
            else:
                list.append(b[-4:-2]) #“无氯”、“低氯”、“中氯”和“高氯”
            
        else:
            list.append('无氯') #没有说明的标为无氯
    data.insert(1,"含氯情况",list)
    return data
data4 = cl(data4)

有机质百分比:

def organic(data):
    list = []
    i = 0
    for i in range(len(data.index)):
        if '复混肥料'== data['技术指标'][i]:
            list.append('0')
        matchObj1=re.search(pattern1,str(data['技术指标'][i]))
 
        
        if matchObj1 != None:#先判断有小括号的
            a = matchObj1.group(2)

            list.append(a)
            
            
        else:
            list.append('未知') #没有说明的标为无氯
            
    data.insert(1,"有机质百分比",list)
    return data
data4 = organic(data4)

运行结果:

  
  
   
  
 

4-2代码

任务4.2比起4.1简单多了,也是使用正则表达式,然后用Python常用方法就可以解决。
这里只有一个函数一定要说,刚学的嘿嘿嘿

n = "123"
s = n.zfill(7)
print(s)

结果:

0000123

可以在前面补全0,超方便有没有!!

 
 

下面就是代码啦:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import re
data4=pd.read_excel("附件4.xlsx",encoding='gbk')#载入数据


def percentage(data,a):
    pattern = r'(.*?)(占(([1-9][0-9]*)+(.[0-9]{1,2})?)'
    num = []#储存百分比的list
    name  = []
    op = []#序号

    tmp = str(data['原料与占比'][a])
    list = tmp.split(',') #根据逗号分割不同成分
        
    
    for p in range(len(list)):
        matchObj1=re.search(pattern,list[p])
        tmpName = str(matchObj1.group(1))
        name.append(tmpName)

        tmpNum = str(matchObj1.group(2))+'%'
        num.append(tmpNum)

        tmpOp = str(p)
        op.append(tmpOp.zfill(3))

    df = {'序号':op,'原料名称':name,'百分比':num}
    df = pd.Dataframe(df)
    return df
    
a = percentage(data4,0)
a.head()

运行结果:

  
    
  

关于Pandas的contains和extract

关于关键字匹配和提取,或许会想到pandas自带的函数contains和extract。
其实我一开始用的就是这个两只,由于正则表达式不熟而且格式转化困难(现在发现可以通过pd.Dataframe()进行转化呜呜呜),所以只能重新用re.match做了一遍(´-ι_-`),痛苦的回忆不愿想起╥﹏╥

这里附上部分代码hhh(任务4-1的含氯情况)

pattern1=r'[u4e00-u9fa5]+氯'
pattern2=r'([u4e00-u9fa5]+氯)'

flag1 = data['技术指标'].str.contains(pattern1,na=False)
flag2 = data['技术指标'].str.contains(pattern2,na=False)#na=False是指nan值为false

a = data['技术指标'].str.extract(r'([u4e00-u9fa5]+氯)', expand=True)
b = data['技术指标'].str.extract(r'[u4e00-u9fa5]+氯', expand=True)
    

思路是先通过contains进行存在判断,进行筛选
再通过相应的extract进行提取

然鹅,
extract提取出来的东西完全不对(Python的re.match就是对的)

  
    
  

以上就是全部啦,干饭去了耶(^-^)V
ε = = (づ′▽`)づ 欢迎评论交流~

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5495678.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-12
下一篇 2022-12-13

发表评论

登录后才能评论

评论列表(0条)

保存