python筛选行政背景_Python气象数据处理笔记:读取复杂文本数据并筛选目标信息...

本期知识点

1、 文本格式资料的读取、分列;

2、 用正则表达式筛选出目标数据;

3、 列表与DataFrame的追加与合并;

4、 字符串的分割

案例分析

以中国气象局提供的“中国ADTD雷电系统定位数据要素数据”为例,数据以文本格式(.txt)按时间存储。数据的表达形式比较复杂,日期以‘-’分隔,时间以‘:’分隔,位置和要素信息以‘中文=’标识,行政区划以‘中文:’标识,且分隔符为多个空格。利用pandas(以下称pd)的read_table() 读取数据时,分隔参数sep=‘ ’选择要慎重,若引号间为一个空格,运行会报错,若引号间用’\t’则不能有效识别分隔,返回一维字符串(仅一列)。

需求

读取文件中信息,年月日时分秒单独立存储,要素与行政区划信息去掉前面的中文和符号描述。

文件打开显示如下:

(点击放大图片)

给出两个处理方案

方案一:分列读取,再通过循环列中的值处理冗余的中文

1、 在利用pd.read_table() 读取文件的时候(代码行1)

分隔符参数‘sep=’用正则表达式’\s+’表示分隔符为一个或多个连续的空格,其意义是:’\s’表示空格,’+’表示有一位或多位。

names=命名列索引,这个参数需要传入一个列表,记得用’[ ]‘括上哦。

header=None声明原数据中没有表头。若原数据中有表头,则在header后面填上表头的行号,记得是从0开始的。

encoding表示读取文件的编码方式,一般在Python的UI界面新建脚本,首行会有‘# -*- coding: utf-8 -*- ‘声明,意思是一下代码默认用UTF-8编码方式。GB2312是常用的中文编码方式,这里就不展开说了。2、 根据数据特征,逐列进行筛选处理

两层嵌套循环,第一层循环的是每一列,第二层循环每列的每一个要素。

我声明了一个新的pd.DataFrame【命名为data_prc】作为完成处理的数据(代码行2),并将原数据的第一列直接赋值给它。其他列完成处理后用pd.concat()实现合并(实际上这里是一个新建的逻辑)。

通过字符串的split()方法,完成每个要素的分割和筛选。split返回一个列表,可用list.append()将处理结果在加载到中间变量temp中,最后与已处理好的其他结果加载到一起。

这里用到的两个拼接有几点需要注意:

list.append(),将括号里的数据加载到list的末尾,更新list,理论上不限制加载的数据类型,list也不用重新赋值(不需要list=list.append());

pd.DataFrame.concat([df1,df2]),将df1和df2进行连接,用其他数据类型会报错,axis=1表示按行拼接(变长),axis=0表示按列进行拼接(变宽)。

pd.concat()不改变原有的数据(需要df_new=pd.concat()才能得到拼接后数据)。

01

具体执行代码如下:

data=pd.read_table(fdir+fl,encoding="GB2312",names=["ID","Date","Time","lat","lon","Intensity","Gradient","err","LocMe","Prov","City","District"],header=None,sep="\s+")data_prc=pd.DataFrame() #创建新DF用于存储处理后的数据data_prc["ID"]=data["ID"]for ite in names[1:]:temp=[] #临时存储单元if ite == "Date":for i in data[ite]:temp.append(i.split("-"))data_prc=pd.concat([data_prc,pd.DataFrame(temp,columns=["Year","Mon","Day"])],axis=1) elif ite == "Time":for i in data[ite]:temp.append(i.split(":"))data_prc=pd.concat([data_prc,pd.DataFrame(temp,columns=["HH","MM","SS"])],axis=1)elif ite in ["lat","lon","Intensity","Gradient","err"]:for i in data[ite]:temp.append(i.split("=")[-1])data_prc=pd.concat([data_prc,pd.DataFrame(temp,columns=[ite])],axis=1)else:foriindata[ite]:temp.append(i.split(":")[-1])data_prc=pd.concat([data_prc,pd.DataFrame(temp,columns=[ite])],axis=1)

这样读出来的数据如下:

!

方案二:用正则表达式逐行处理

这个方案用到了正则表达式库re,需要在代码开头import re,在定义匹配模板pattern的时候,把序号ID跳过了,所以最后的数据处理结果没有序号列。

1、 定义正则表达式模板pattern

模板用字符串表示(就是引号括起来),引号前的r表示原生字符(正则表达式里使用"\"作为转义字符,也就是‘\\s‘在计算机看来才是‘\s‘,原来的’\s‘是一个空格),

为了我等粗心人再也不用担心漏写反斜杠’,推荐大家用r的。

将需要提取的内容用小括号括起来,具体正则表达式规则大家可以去看看官方文档,这就介绍本案例用到的几个:

i.\d表示任意数字字符(和[0-9]一个意思),{number}表示前面这个会出现number次,所以

’\d{4}’就表示‘

这里会有4个数字’

ii.?表示前面这个会出现0或任意次,

‘(-?\d+\.?\d?’表示一个可负可正的浮点数,由一个可能出现的负号

’-?’,一个任意长度的数字

‘\d+‘一个可能存在的点

’\.?‘和另一个任意长度的数字

‘\d? ’组成。

iii.\w(小写哦)表示非特殊字符,包括字母、汉字、数字、下划线

iv.其他要完全一致的信息,直接原样写到字符串中就可以了

v.最后一个技术细节,用一个小括号吧pattern引号里的内容都括起来,否则会报错

2、 读取数据行数,逐行处理数据

在数据读取时,我没有给data赋值列名,系统会自动分配列名为0,所以代码第6行我表示某一列时,列索引用[0]。DA[0][i]表示第0列的第i行

用re.findall(pattern,dat)将找到dat中所有能匹配pattern规则的东西,返回值rep从第二个要素开始(rep[0][1:])取就是我们需要的数据啦。第一个要素是所有值,对应V.中的括号。

3、将处理结果转为pd.DataFrame结构(代码行9),并赋值列名

01

具体执行代码如下:DA=pd.read_table(fdir,encoding="GB2312",header=None)pattern=r".*((\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d+\.?\d+)\s+纬度=(\d+\.?\d+)\s+经度=(\d+\.?\d+)\s+强度=(-?\d+\.?\d+)\s+陡度=(-?\d+\.?\d+)\s+误差=(-?\d+\.?\d*)\s+定位方式:(\d*)\s+省:(\w*)\s+市:(\w*)\s+县:(\w*))"(n,m)=DA.shapeline=[]for i in np.arange(m):dat=DA[0][i]rep=re.findall(pattern,dat) line.append(rep[0][1:])df=pd.DataFrame(line,columns=["Year","Mon","Day","HH","MM","SS","lat","lon","Intensity","Gradient","err","LocMe","Prov","City","Distric"])

如果只想取某个地区的数据,在循环处理前加个字符串包含(if a in b:)的判断就可以跳过不想要的行了,这样处理效率会更高。

这样获取的数据结果如下:

TIPS:

在处理文件I/O时有python和C两个引擎,可以用关键字’engine=’进行定义使用的分析引擎。可以选择C或者是python,C引擎快但是Python引擎功能更多些。上述功能中,C引擎支持的正侧表达式不能超过一位("c" engine does not support regex separators > 1 char)

END

文字

||

罗鼓手说挺好的

排版

||星星伴月

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值