返回介绍

01. Python 工具

02. Python 基础

03. Numpy

04. Scipy

05. Python 进阶

06. Matplotlib

07. 使用其他语言进行扩展

08. 面向对象编程

09. Theano 基础

10. 有趣的第三方模块

11. 有用的工具

12. Pandas

数组读写

发布于 2022-09-03 20:46:13 字数 19370 浏览 0 评论 0 收藏 0

从文本中读取数组

In [1]:

import numpy as np

空格(制表符)分割的文本

假设我们有这样的一个空白分割的文件:

In [2]:

%%writefile myfile.txt
2.1 2.3 3.2 1.3 3.1
6.1 3.1 4.2 2.3 1.8
Writing myfile.txt

为了生成数组,我们首先将数据转化成一个列表组成的列表,再将这个列表转换为数组:

In [3]:

data = []

with open('myfile.txt') as f:
    # 每次读一行
    for line in f:
        fileds = line.split()
        row_data = [float(x) for x in fileds]
        data.append(row_data)

data = np.array(data)

In [4]:

data

Out[4]:

array([[ 2.1,  2.3,  3.2,  1.3,  3.1],
       [ 6.1,  3.1,  4.2,  2.3,  1.8]])

不过,更简便的是使用 loadtxt 方法:

In [5]:

data = np.loadtxt('myfile.txt')
data

Out[5]:

array([[ 2.1,  2.3,  3.2,  1.3,  3.1],
       [ 6.1,  3.1,  4.2,  2.3,  1.8]])

逗号分隔文件

In [6]:

%%writefile myfile.txt
2.1, 2.3, 3.2, 1.3, 3.1
6.1, 3.1, 4.2, 2.3, 1.8
Overwriting myfile.txt

对于逗号分隔的文件(通常为.csv格式),我们可以稍微修改之前繁琐的过程,将 split 的参数变成 ','即可。

不过,loadtxt 函数也可以读这样的文件,只需要制定分割符的参数即可:

In [7]:

data = np.loadtxt('myfile.txt', delimiter=',')
data

Out[7]:

array([[ 2.1,  2.3,  3.2,  1.3,  3.1],
       [ 6.1,  3.1,  4.2,  2.3,  1.8]])

loadtxt 函数

loadtxt(fname, dtype=<type 'float'>, 
        comments='#', delimiter=None, 
        converters=None, skiprows=0, 
        usecols=None, unpack=False, ndmin=0)

loadtxt 有很多可选参数,其中 delimiter 就是刚才用到的分隔符参数。

skiprows 参数表示忽略开头的行数,可以用来读写含有标题的文本

In [8]:

%%writefile myfile.txt
X Y Z MAG ANG
2.1 2.3 3.2 1.3 3.1
6.1 3.1 4.2 2.3 1.8
Overwriting myfile.txt

In [9]:

np.loadtxt('myfile.txt', skiprows=1)

Out[9]:

array([[ 2.1,  2.3,  3.2,  1.3,  3.1],
       [ 6.1,  3.1,  4.2,  2.3,  1.8]])

此外,有一个功能更为全面的 genfromtxt 函数,能处理更多的情况,但相应的速度和效率会慢一些。

genfromtxt(fname, dtype=<type 'float'>, comments='#', delimiter=None, 
           skiprows=0, skip_header=0, skip_footer=0, converters=None, 
           missing='', missing_values=None, filling_values=None, usecols=None, 
           names=None, excludelist=None, deletechars=None, replace_space='_', 
           autostrip=False, case_sensitive=True, defaultfmt='f%i', unpack=None, 
           usemask=False, loose=True, invalid_raise=True)

loadtxt 的更多特性

对于这样一个文件:

In [10]:

%%writefile myfile.txt
 -- BEGINNING OF THE FILE
% Day, Month, Year, Skip, Power
01, 01, 2000, x876, 13 % wow!
% we don't want have Jan 03rd
04, 01, 2000, xfed, 55
Overwriting myfile.txt

In [11]:

data = np.loadtxt('myfile.txt', 
                  skiprows=1,         #忽略第一行
                  dtype=np.int,      #数组类型
                  delimiter=',',     #逗号分割
                  usecols=(0,1,2,4), #指定使用哪几列数据
                  comments='%'       #百分号为注释符
                 )
data

Out[11]:

array([[   1,    1, 2000,   13],
       [   4,    1, 2000,   55]])

loadtxt 自定义转换方法

In [12]:

%%writefile myfile.txt
2010-01-01 2.3 3.2
2011-01-01 6.1 3.1
Overwriting myfile.txt

假设我们的文本包含日期,我们可以使用 datetimeloadtxt 中处理:

In [13]:

import datetime

def date_converter(s):
    return datetime.datetime.strptime(s, "%Y-%m-%d")

data = np.loadtxt('myfile.txt',
                  dtype=np.object, #数据类型为对象
                  converters={0:date_converter,  #第一列使用自定义转换方法
                              1:float,           #第二第三使用浮点数转换
                              2:float})

data

Out[13]:

array([[datetime.datetime(2010, 1, 1, 0, 0), 2.3, 3.2],
       [datetime.datetime(2011, 1, 1, 0, 0), 6.1, 3.1]], dtype=object)

移除 myfile.txt

In [14]:

import os
os.remove('myfile.txt')

读写各种格式的文件

如下表所示:

文件格式使用的包函数
txtnumpyloadtxt, genfromtxt, fromfile, savetxt, tofile
csvcsvreader, writer
Matlabscipy.ioloadmat, savemat
hdfpytables, h5py
NetCDFnetCDF4, scipy.io.netcdfnetCDF4.Dataset, scipy.io.netcdf.netcdf_file
文件格式使用的包备注
wavscipy.io.wavfile音频文件
jpeg,png,...PIL, scipy.misc.pilutil图像文件
fitspyfits天文图像

此外, pandas ——一个用来处理时间序列的包中包含处理各种文件的方法,具体可参见它的文档:

http://pandas.pydata.org/pandas-docs/stable/io.html

将数组写入文件

savetxt 可以将数组写入文件,默认使用科学计数法的形式保存:

In [15]:

data = np.array([[1,2], 
                 [3,4]])

np.savetxt('out.txt', data)

In [16]:

with open('out.txt') as f:
    for line in f:
        print line,
1.000000000000000000e+00 2.000000000000000000e+00
3.000000000000000000e+00 4.000000000000000000e+00

也可以使用类似C语言中 printf 的方式指定输出的格式:

In [17]:

data = np.array([[1,2], 
                 [3,4]])

np.savetxt('out.txt', data, fmt="%d") #保存为整数

In [18]:

with open('out.txt') as f:
    for line in f:
        print line,
1 2
3 4

逗号分隔的输出:

In [19]:

data = np.array([[1,2], 
                 [3,4]])

np.savetxt('out.txt', data, fmt="%.2f", delimiter=',') #保存为2位小数的浮点数,用逗号分隔

In [20]:

with open('out.txt') as f:
    for line in f:
        print line,
1.00,2.00
3.00,4.00

复数值默认会加上括号:

In [21]:

data = np.array([[1+1j,2], 
                 [3,4]])

np.savetxt('out.txt', data, fmt="%.2f", delimiter=',') #保存为2位小数的浮点数,用逗号分隔

In [22]:

with open('out.txt') as f:
    for line in f:
        print line,
 (1.00+1.00j), (2.00+0.00j)
 (3.00+0.00j), (4.00+0.00j)

更多参数:

savetxt(fname, 
        X, 
        fmt='%.18e', 
        delimiter=' ', 
        newline='\n', 
        header='', 
        footer='', 
        comments='# ')

移除 out.txt

In [23]:

import os
os.remove('out.txt')

Numpy 二进制格式

数组可以储存成二进制格式,单个的数组保存为 .npy 格式,多个数组保存为多个.npy文件组成的 .npz 格式,每个 .npy 文件包含一个数组。

与文本格式不同,二进制格式保存了数组的 shape, dtype 信息,以便完全重构出保存的数组。

保存的方法:

  • save(file, arr) 保存单个数组,.npy 格式
  • savez(file, *args, **kwds) 保存多个数组,无压缩的 .npz 格式
  • savez_compressed(file, *args, **kwds) 保存多个数组,有压缩的 .npz 格式

读取的方法:

  • load(file, mmap_mode=None) 对于 .npy,返回保存的数组,对于 .npz,返回一个名称-数组对组成的字典。

单个数组的读写

In [24]:

a = np.array([[1.0,2.0], [3.0,4.0]])

fname = 'afile.npy'
np.save(fname, a)

In [25]:

aa = np.load(fname)
aa

Out[25]:

array([[ 1.,  2.],
       [ 3.,  4.]])

删除生成的文件:

In [26]:

import os
os.remove('afile.npy')

二进制与文本大小比较

In [27]:

a = np.arange(10000.)

保存为文本:

In [28]:

np.savetxt('a.txt', a)

查看大小:

In [29]:

import os
os.stat('a.txt').st_size

Out[29]:

260000L

保存为二进制:

In [30]:

np.save('a.npy', a)

查看大小:

In [31]:

os.stat('a.npy').st_size

Out[31]:

80080L

删除生成的文件:

In [32]:

os.remove('a.npy')
os.remove('a.txt')

可以看到,二进制文件大约是文本文件的三分之一。

保存多个数组

In [33]:

a = np.array([[1.0,2.0], 
              [3.0,4.0]])
b = np.arange(1000)

保存多个数组:

In [34]:

np.savez('data.npz', a=a, b=b)

查看里面包含的文件:

In [35]:

!unzip -l data.npz
Archive:  data.npz
  Length      Date    Time    Name
---------  ---------- -----   ----
      112  2015/08/10 00:46   a.npy
     4080  2015/08/10 00:46   b.npy
---------                     -------
     4192                     2 files

载入数据:

In [36]:

data = np.load('data.npz')

载入后可以像字典一样进行操作:

In [37]:

data.keys()

Out[37]:

['a', 'b']

In [38]:

data['a']

Out[38]:

array([[ 1.,  2.],
       [ 3.,  4.]])

In [39]:

data['b'].shape

Out[39]:

(1000L,)

删除文件:

In [40]:

# 要先删除 data,否则删除时会报错
del data

os.remove('data.npz')

压缩文件

当数据比较整齐时:

In [41]:

a = np.arange(20000.)

无压缩大小:

In [42]:

np.savez('a.npz', a=a)
os.stat('a.npz').st_size

Out[42]:

160188L

有压缩大小:

In [43]:

np.savez_compressed('a2.npz', a=a)
os.stat('a2.npz').st_size

Out[43]:

26885L

大约有 6x 的压缩效果。

当数据比较混乱时:

In [44]:

a = np.random.rand(20000.)

无压缩大小:

In [45]:

np.savez('a.npz', a=a)
os.stat('a.npz').st_size

Out[45]:

160188L

有压缩大小:

In [46]:

np.savez_compressed('a2.npz', a=a)
os.stat('a2.npz').st_size

Out[46]:

151105L

只有大约 1.06x 的压缩效果。

In [47]:

os.remove('a.npz')
os.remove('a2.npz')

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文