数据的CSV文件存取

CSV是英文Comma Separate Values(逗号分隔符)的缩写, 顾名思义, 文档的内容是由 “,” 分隔的一列列的数据构成的. CSV文档是一种编辑方便, 可视化效果极佳的数据存储方式. Python的Numpy库中有很多处理这种文档的方法.

存入CSV文件

存入CSV:

np.savetxt(frame, X, fmt=’%.18e’, delimiter=’ ‘, newline=’\n’, header=’’, footer=’’, comments=’#’ , encoding=None) [官方文档]

  • frame: 文件, 字符串或产生器, 可以是.gz或.bz2的压缩文件
  • X: 一维或二维ndarry数据, 将被存入文件中
  • fmt: 写入文件的格式, 如%d, %.2f等
  • delimiter: 用于列分割的字符串, 默认是空格
  • newline: 用于行分割的字符串, 默认是换行
  • header: 写在文件头部的字符串
  • footer: 写在文件尾部的字符串
  • comments: 注释
  • encoding: 编码格式

例如:

1
2
3
4
import numpy as np

a = np.arange(100).reshape((20, 5))
np.savetxt("a.csv", a, fmt="%d", delimiter=",", header="我来组成头部", footer="我来组成尾部")

输出的文件为:

01

读取CSV文件

读取CSV:

numpy.loadtxt(fname, dtype=, comments=’#’, delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, ndmin=0, encoding=’bytes’, max_rows=None) [官方文档]

  • frame: 文件, 字符串或产生器, 可以是.gz或.bz2的压缩文件
  • dtype: 数据类型, 可选, 如 np.float, np.int32等
  • comments: 注释
  • delimiter: 用于列分割的字符串, 默认是空格
  • converters: 根据字典将读取的数据自动转换
  • skiprows: 跳过前几行, 包括注释, 默认为0
  • usecols: 要读取的列数, 其中0为第一列. 例如, usecols=(1, 4, 5)将提取第2、第5和第6列. 默认None读取所有列
  • unpack: 默认为False, 如果为True时读入属性将分别写入不同的数组变量
  • ndmin: 返回的ndarry将至少具有ndmin维度. 否则, ndarry将被升维
  • encoding: 编码格式, 默认为bytes
  • max_row: 在skiprows后读取的行数, 默认Node是读取所有行

这里我们读取a.csv文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import numpy as np

b = np.loadtxt("a.csv", dtype=np.int, delimiter=",", skiprows=1, max_rows=20)
print(b)
# 输出结果为:
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]
[20 21 22 23 24]
[25 26 27 28 29]
[30 31 32 33 34]
[35 36 37 38 39]
[40 41 42 43 44]
[45 46 47 48 49]
[50 51 52 53 54]
[55 56 57 58 59]
[60 61 62 63 64]
[65 66 67 68 69]
[70 71 72 73 74]
[75 76 77 78 79]
[80 81 82 83 84]
[85 86 87 88 89]
[90 91 92 93 94]
[95 96 97 98 99]]

注意:
csv只能用有效存储一维和二维数据, np.savetxt()和np.loadtxt()也只能有效存取一维和二维数组

多维数据的存取

存入多维数据

存入多维数据:

a.tofile(file, sep=””, format=”%s”) [官方文档]

  • file: 文件, 字符串
  • sep: 数据分割字符串,如果为空串, 写入文件为二进制
  • format: 写入文件的格式

例如:

1
2
3
4
import numpy as np

a = np.arange(100).reshape((2, 5, 10))
a.tofile("a.bat", sep=",", format="%d")

读取多维数据

读取多维数据:

np.fromfile(file, dtype=float, count=-1, sep=””) [官方文档]

  • file: 文件, 字符串
  • dtype: 读取的数据类型
  • count: 读入元素个数, 默认-1表示读入整个文件
  • sep: 数据分割字符串,如果为空串, 读入文件为二进制

这里我们再用fromfile读取a.bat文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import numpy as np

b = np.fromfile("a.bat", dtype=np.int, sep=",").reshape((2, 5, 10))
print(b)
# 输出结果为:
[[[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24 25 26 27 28 29]
[30 31 32 33 34 35 36 37 38 39]
[40 41 42 43 44 45 46 47 48 49]]

[[50 51 52 53 54 55 56 57 58 59]
[60 61 62 63 64 65 66 67 68 69]
[70 71 72 73 74 75 76 77 78 79]
[80 81 82 83 84 85 86 87 88 89]
[90 91 92 93 94 95 96 97 98 99]]]

注意:
该方法需要读取时知道存入文件时数组的维度和元素类型, 而且两个方法需要配合使用, 可以再增加一个文件存储数组维度和元素类型信息
当然也可以使用NumPy自带的.npy或压缩文件.npz来存储文件, 此时不需要数组维度和类型信息

NumPy的便捷文件存取

便捷存取数据:

numpy.save(file, arr, allow_pickle=True, fix_imports=True) [官方文档]
numpy.load(file, mmap_mode=None, allow_pickle=False, fix_imports=True, encoding=’ASCII’) [官方文档]

  • file: 文件名, 以.npy为扩展名, 压缩扩展名为.npz
  • arr: ndarry数组变量
  • allow_pickle: 允许使用Python pickle保存对象数组. 不允许使用Pickle的原因包括安全性(加载Pickle数据可以执行任意代码)和可移植性(Pickle对象可能不能在不同的Python版本上加载). 默认为True
  • fix_imports: 如果为True, Pickle将尝试将新的Python3名称映射到Python2中使用的旧模块名称, 以便Pickle数据流可以用Python2读取
  • mmap_mode: (None, ‘r+’, ‘r’, ‘w+’, ‘c’), 如果不是None, 则使用给定模式对文件进行内存映射(有关模式的详细说明, 请参见numpy.memmap)

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np

a = np.arange(100).reshape((2, 5, 10))
np.save("a.npy", a)
b = np.load("a.npy")
print(b)
# 输出结果为:
[[[ 0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24 25 26 27 28 29]
[30 31 32 33 34 35 36 37 38 39]
[40 41 42 43 44 45 46 47 48 49]]

[[50 51 52 53 54 55 56 57 58 59]
[60 61 62 63 64 65 66 67 68 69]
[70 71 72 73 74 75 76 77 78 79]
[80 81 82 83 84 85 86 87 88 89]
[90 91 92 93 94 95 96 97 98 99]]]

NumPy的随机函数random库

np.random的随机数函数(1)

函数 说明
np.random.rand(d0, d1, …, dn) 根据d0-dn创建随机数数组, 浮点数, [0, 1), 均匀分布
np.random.randn(d0, d1, …, dn) 根据d0-dn创建随机数数组, 标准正态分布
np.random.randint(low, high=None, size=None, dtype=’l’) 根据size创建随机整数或整数数组, 范围是[low, high)
np.random.seed(seed=None) 随机数种子, seed是给定的种子

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> import numpy as np
>>> a = np.random.rand(3, 4)
>>> a
array([[0.45087219, 0.49898615, 0.14812819, 0.46831802],
[0.5471714 , 0.70220481, 0.81879441, 0.28438397],
[0.24157713, 0.08734116, 0.31917848, 0.2113096 ]])
>>> b = np.random.randn(3, 4)
>>> b
array([[-0.78826698, -1.11178575, 0.14375318, -0.80170188],
[ 0.07668368, 0.20256562, -0.01035406, -0.20920067],
[ 0.4288885 , -0.32967433, -0.80390139, 1.57414189]])
>>> c = np.random.randint(100, 200, (3, 4))
>>> c
array([[139, 159, 115, 175],
[131, 119, 125, 131],
[191, 158, 175, 181]])

这是三种创建随机数组的方法, 事实上所有编程创建随机数的方法都是伪随机, 根据随机数种子生成的随机数, 相同的种子生成的随机数相同.
例如:

1
2
3
4
5
6
7
8
9
10
11
12
>>> np.random.seed(10)
>>> d = np.random.randint(1, 100, (3, 4))
>>> d
array([[10, 16, 65, 29],
[90, 94, 30, 9],
[74, 1, 41, 37]])
>>> np.random.seed(10)
>>> e = np.random.randint(1, 100, (3, 4))
>>> e
array([[10, 16, 65, 29],
[90, 94, 30, 9],
[74, 1, 41, 37]])

可以看到, 在随机数种子相同的情况下, 使用randint生成的ndarry完全相同.

np.random的随机数函数(2)

函数 说明
np.random.shuffle(x) 根据数组x的第1轴进行随机排列, 改变ndarry数组x
np.random.permutation(x) 根据数组x的第1轴进行随机排列并生成一个新的数组, 不改变数组x
np.random.choice(a, size=None, replace=True, p=None) 从一维数组a中以概率p抽取元素, 形成size形状的新数组, replace表示是否可以重用元素, 默认为True

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> import numpy as np
>>> a = np.random.randint(1, 100, (3, 4))
>>> a
array([[96, 44, 73, 12],
[91, 71, 6, 4],
[76, 80, 54, 73]])
>>> np.random.shuffle(a)
>>> a
array([[91, 71, 6, 4],
[76, 80, 54, 73],
[96, 44, 73, 12]])
>>> b = np.random.permutation(a)
>>> a
array([[91, 71, 6, 4],
[76, 80, 54, 73],
[96, 44, 73, 12]])
>>> b
array([[96, 44, 73, 12],
[91, 71, 6, 4],
[76, 80, 54, 73]])

通过例子可以看出, 乱序只是针对第一轴进行, 并不是完全乱序.而且shuffle会改变原数组, 而permutation并不会改变原数组.

1
2
3
4
5
6
7
8
9
10
11
12
>>> import numpy as np
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b = np.random.choice(a, (2, 3))
>>> b
array([[3, 4, 7],
[7, 8, 2]])
>>> c = np.random.choice(a, (2, 3), replace=False)
>>> c
array([[1, 2, 3],
[7, 5, 6]])

需要注意, a必须为一维数组, 而choice函数中的参数replace代表是否可以重用元素, 默认是可以.

np.random的随机数函数(3)

还有一些比较特殊的随机生成数组的函数

函数 说明
np.random.uniform(low=0.0, high=1.0, size=None) 根据size创建具有均匀分布的数组, 范围是[low, high)
np.random.normal(loc=0.0, scale=1.0, size=None) 根据size创建具有正态分布的数组, loc为均值, scale为标准差
np.random.poisson(lam=1.0, size=None) 根据size创建具有泊松分布的数组, lam为随机事件发生率

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
>>> import numpy as np
>>> a = np.random.uniform(0, 10, (100, ))
>>> a
array([0.18353162, 4.54815419, 9.02359159, 1.31611705, 6.95712441,
6.73981602, 6.58880064, 1.84570526, 8.04029002, 8.42096203,
4.74099761, 3.92605393, 4.68382957, 3.07500946, 1.29849494,
3.9577049 , 5.13901914, 0.97433299, 5.26476539, 3.09737276,
9.35394762, 9.1925425 , 8.50152632, 6.79535765, 8.03265246,
9.65915457, 1.55158244, 8.1674295 , 8.23028456, 3.76012042,
9.84322743, 5.40619576, 5.26457822, 0.35969245, 3.80279463,
6.74808604, 2.09194296, 0.13124456, 8.19259391, 6.64428158,
3.45591224, 9.68167834, 5.78461556, 1.30257213, 4.83656765,
2.48088801, 9.45927289, 9.40271488, 5.74138226, 1.29015172,
1.21143295, 2.09859459, 3.78118623, 7.59712 , 1.93045901,
0.91097244, 9.21861302, 5.07305017, 3.19887584, 6.64391771,
3.86870022, 5.31809733, 8.4912826 , 3.16542846, 4.96103839,
8.54998476, 7.36554195, 1.49972447, 6.81252561, 3.65335119,
7.15748543, 6.49474763, 7.85070303, 6.45675507, 2.86792818,
5.10746017, 6.06247653, 0.24215072, 2.89880406, 3.2611604 ,
1.85125799, 2.29038522, 1.93074919, 4.64083656, 9.65045059,
5.78024413, 2.06289661, 1.4891531 , 0.58710547, 1.04414851,
7.9122271 , 0.86434308, 3.98958612, 7.48409308, 8.29518132,
6.42560628, 1.31952008, 8.13094665, 3.79248694, 3.58716165])
>>> b = np.random.normal(20, 5, (100, ))
>>> b
array([11.3530248 , 20.48006996, 10.98112656, 17.58877478, 25.20259957,
21.56756176, 20.40115027, 14.70432795, 18.06893029, 25.49112036,
24.10024301, 19.194503 , 18.17725825, 21.25358689, 18.88552295,
21.27836803, 18.81384053, 15.69917296, 13.34113949, 11.03058634,
15.56351578, 20.56509462, 11.11847565, 17.99800174, 12.40474617,
21.03028557, 14.63894791, 19.04553478, 28.45902187, 27.08408711,
19.06542874, 25.14527098, 19.49086574, 15.1463953 , 20.30209885,
29.75413616, 18.29336661, 19.03508919, 25.39763073, 20.24196635,
24.52959575, 17.3307682 , 24.66246541, 24.18848444, 20.9142996 ,
13.85222808, 22.40808697, 22.21325262, 17.56817619, 16.1616764 ,
21.73701134, 17.88132244, 21.23923888, 17.55331955, 13.80796819,
24.92732515, 17.12310385, 28.65652659, 20.52694997, 27.01473676,
12.95946234, 17.28702462, 20.31428889, 24.67703164, 6.39452612,
14.21719986, 26.53790329, 16.2946598 , 21.13457024, 24.08655186,
24.17378991, 23.21012897, 19.53873781, 10.59165471, 13.5912755 ,
13.47296729, 23.87651404, 24.85452569, 14.01361586, 22.86241457,
25.9329148 , 29.163893 , 16.73786565, 14.13756469, 21.15530961,
19.71695147, 25.12742265, 12.49209888, 25.51647627, 24.72324514,
20.47430207, 16.35965267, 18.69875974, 21.33813756, 17.41537074,
13.43509534, 26.64436397, 23.36228966, 13.18294489, 25.71251717])
>>> c = np.random.poisson(4, (100, ))
>>> c
array([ 3, 5, 3, 5, 2, 2, 3, 2, 4, 8, 6, 1, 4, 3, 9, 4, 1,
2, 2, 7, 3, 2, 3, 10, 3, 7, 3, 5, 4, 2, 3, 5, 6, 1,
3, 6, 3, 4, 1, 4, 2, 3, 6, 3, 3, 1, 5, 3, 2, 8, 5,
3, 2, 2, 5, 4, 5, 5, 2, 3, 5, 5, 10, 3, 3, 4, 0, 2,
2, 6, 0, 7, 4, 3, 3, 5, 2, 6, 3, 2, 5, 4, 6, 4, 0,
8, 2, 3, 4, 5, 3, 6, 1, 2, 3, 5, 5, 2, 4, 4])

均匀分布数组a的直方图:

02

正态分布数组b的直方图:

03

泊松分布数组c的直方图:

04