python用于科学计算可行吗_Python科学计算——File I/O

Python 获取数据的方式有很多:(1) 如果在命令行运行 Python 脚本,你可以用 sys.stdin 和 sys.stdout 以管道 (pipe) 方式传递数据;(2) 可以显式地用代码来读写文件获取数据;(3) 从网页获取数据,也就是所谓的爬虫 (web spider);(4) 使用 API (Application Programming Interface) 获取结构化格式的数据。 而在科学计算领域,更多的是处理实验中所获得的数据,比如:传感器,采集卡,示波器,光谱仪等仪器采集的数据。

案例一:温度传感器 (temperature sensor) 数据

本案例所采用的数据是热敏电阻 (thermistor) 采集的被加热物体的温度信息数据,其以如下格式存储在txt文件中:

1 2016-04-10 21:31:08.781 49.9492

2 2016-04-10 21:31:09.296 49.9589

3 2016-04-10 21:31:09.811 49.964

4 2016-04-10 21:31:10.326 49.9741

5 2016-04-10 21:31:10.841 49.983

...

处理文本文件的第一步是通过 open 命令来获取一个文件对象:

file_for_reading = open('thermistor.txt', 'r') # 'r' 意味着只读

file_for_writing = open('thermistor.txt', 'w') # 'w' 是写入

file_for_appending = open('thermistor.txt', 'a') # 'a' 是添加

file_for_xxx.close() # 完成操作后要关闭文件

因为非常容易忘记关闭文件,所以应该在 with 程序块里操作文件,这样结尾处文件会被自动关闭:

with open('thermistor.txt', 'r') as f:

data = function_that_gets_data_form(f) # 获取数据函数

此时,f 已经关闭了,就不能试图使用它啦,然后对数据执行相应的操作即可。

process(data) # 处理数据函数

处理文本文件第二步是观察数据特征,选择合适的读取命令:通过观察,可以发现,文件没有头部,每一行包括三种数据 (编号,时间,温度) 他们之间以空格键分开,每一列是同一类数据,这样我们就可以用 Python 中的 csv 模块中的 csv.reader 对其进行迭代处理,每一行都会被处理成恰当划分的列表。

import csv

with open(r"thermistor.txt","rb") as f:

reader = csv.reader(f,delimiter='\t')

number=[]

time = []

data=[]

for row in reader:

number.append(row[0])

time.append(row[1])

data.append(float(row[2]))

处理文本文件的第三步是检测数据读取格式是否正确,我们可以用如下的方式检测:

>>> print number[0], time[0], data[0]

>>> 1 2016-04-10 21:31:08.781 49.9492

从输出的首个元素来看,以上的读取数据的方式是没有问题的,但是到这里我们并不能完全放心我们的数据格式:

>>> print number[0:3], time[0:3], data[0:3]

>>> ['\xef\xbb\xbf1', '2', '3']

['2016-04-10 21:31:08.781', '2016-04-10 21:31:09.296', '2016-04-10 21:31:09.811']

[49.9492, 49.9589, 49.964]

当我们以列表的形式输出时,number 中的首个元素出现了我们没有预料到的“乱码”,这其实是 BOM (byte order mark), 它是为 UTF-16 和 UTF-32 准备的,用以标记字节序。微软在 UTF-8 中使用 BOM 是因为这样可以把 UTF-8 和 ASCII 等编码区别开,但这样的文件会给我们的数据读取带来问题。还好,我们可以用 Python 中的 codecs 模块解决这个问题。

import csv

import codecs

with codecs.open(r"thermistor.txt","rb","utf-8-sig") as f:

reader = csv.reader(f,delimiter='\t')

number=[]

time=[]

data=[]

for row in reader:

number.append(row[0])

time.append(row[1])

data.append(float(row[2]))

此时,我们再以列表形式输出时,就会得到正确的结果:

>>> ['1', '2', '3']

['2016-04-10 21:31:08.781', '2016-04-10 21:31:09.296', '2016-04-10 21:31:09.811']

[49.9492, 49.9589, 49.964]

然后就可以用得到的数据进行处理分析啦~

案例二:示波器 (oscilloscope) 数据

有了上面的经验,我们直接从处理文本文件第二步开始,示波器数据相对上面的数据,复杂的地方在于它包含了表头信息,而这些信息大部分时间是处理数据中不太需要的,它的数据格式如下:

Type: raw

Points: 16200

Count: 1

XInc: 1.23457E-013

XOrg: 2.4000000000E-008

YData range: 1.48000E-001

YData center: 5.00000E-004

Coupling: 50 Ohms

XRange: 2.00000E-009

XOffset: 2.4000000000E-008

YRange: 1.44000E-001

YOffset: 5.00000E-004

Date: 18 APR 2016

Time: 16:00:54:74

Frame: 86100C:MY46520443

X Units: second

Y Units: Volt

XY Data:

2.4000000E-008, 1.4349E-002

2.4000123E-008, 1.6005E-002

2.4000247E-008, 1.5455E-002

2.4000370E-008, 1.5702E-002

2.4000494E-008, 1.5147E-002

...

可以看出,“表头”是一些参数信息,真正有用的数据是从 “XY Data:” 下一行开始的,对于这样的数据有两种方法进行读取:(1) 直接跳过“表头”读取数据;(2) 利用正则表达式寻找“表头” 和数据的不同特征进行识别读取。

with open(r"waveform.txt","rb") as f:

lines = f.readlines()

x=[]

y=[]

for line in lines[18:]:

x.append(float(line.replace("\r\n","").split(",")[0]))

y.append(float(line.replace("\r\n","").split(",")[1]))

通过观察我们发现有效数据是从第19行开始的,于是我们直接从19行开始读取数据,跳过“表头”,以列表形式输出 x 和 y 前3个元素如下:

>>> [2.4e-08, 2.4000123e-08, 2.4000247e-08]

[0.014349, 0.016005, 0.015455] # 数据读取正确

运用正则表达式读取数据的关键在于找到有效数据行的独有特征,这里以 “E-002” 作为有效数据行区别于“表头”的特征,对数据的读取方式如下:

import re

with open(r"waveform.txt","rb") as f:

lines = f.readlines()

x=[]

y=[]

for line in lines:

if re.search('E-002',line):

x.append(float(line.replace("\r\n","").split(",")[0]))

y.append(float(line.replace("\r\n","").split(",")[1]))

同样,以列表形式输出 x 和 y 前3个元素用于检验:

>>> [2.4e-08, 2.4000123e-08, 2.4000247e-08]

[0.014349, 0.016005, 0.015455] # 数据读取正确

注:具体的数据读取方式要根据具体文本文件的特征决定,运用合适的方法才能得到更好的结果。

案例三:二维数据写入

很多时候,经过 process( ) 后的数据,需要备份留用或者供其他程序调用,因此,将处理后的数据写入文本文件也将是关键的一步。根据数据读入的经验,被读入的数据经常存储在 list 中,那么处理后数据也通常存储在 list 中,因此,以 list 的写入作为例子:

x = [1, 2, 3, 4]

y = [2.0, 4.0, 6.0, 8.0] # 参考数据

接下来就要考虑的是要以什么样的格式保存数据,为了更加直观的表现数据的关系,我们将 x,y 分别保存为一列,中间以空格键隔开,那么 csv.writer( ) 将是很好的工具:

xy = {}

for i in range(len(x)):

xy[x[i]] = y[i]

with open(r"15.txt", 'wb') as f:

writer = csv.writer(f,delimiter='\t')

for x, y in xy.items():

writer.writerow([x, y])

为了同时保存 x 和 y 的对应值,这里把 x 和 y 写入字典,x 为键 (key), y 为 值 (value) ,xy 就是 x 和 y 构成的字典。保存后的数据格式如下所示:

1 2.0

2 4.0

3 6.0

4 8.0

案例四:多维数据写入

由于字典的键 (key) 和值 (value) 对应的特殊数据结构,写入二维数据较为方便,对于多维数据,我们就需要构建多维矩阵,或者列表与元组结合的方式录入:

x = [1, 2, 3, 4]

y = [2.0, 4.0, 6.0, 8.0]

z = [3.0, 6.0, 9.0, 12.0]

这里以三维数据为例子。同样,需要将 x,y,z 各一列写入到txt中:

xyz = []

for i in range(len(x)):

xyz.append([x[i],y[i],z[i]])

with open(r"15.txt", 'wb') as f:

writer = csv.writer(f,delimiter='\t')

for x, y, z in xyz:

writer.writerow([x, y, z])

这样,就可以很容易地得到需要的数据格式的文本文件:

1 2.0 3.0

2 4.0 6.0

3 6.0 9.0

4 8.0 12.0

Stay hungry, Stay foolish. -- Steve Jobs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值