目前为止,介绍的numpy
数组基本都是关于数值的,其实,numpy
本身就是一个用于数值计算的基础库。
不过,除了数值计算之外,numpy
也能够支持结构化数组。
numpy
的数组为了提高计算性能,要求数组的数据类型要一致。
但是现实情况下,我们经常遇到不是纯数值的数组,比如:
name = ["harry", "tom", "annie"]
sex = ["male", "male", "female"]
age = [40, 31, 14]
arr = np.array([name, sex, age])
print(arr)
#运行结果
[['harry' 'tom' 'annie']
['male' 'male' 'female']
['40' '31' '14']]
上面三个数组的类型不一致,放到一个numpy
数组中时,可以看出,age
数组被自动转换为字符串类型了。
为了保持 age
数组的原有数据类型,就要用到numpy
的结构化数组了。
arr = np.zeros(
3,
dtype={"names": ("name", "sex", "age"),
"formats": ("U10", "U10", "i4")},
)
print(arr)
#运行结果
[('', '', 0) ('', '', 0) ('', '', 0)]
arr["name"] = name
arr["sex"] = sex
arr["age"] = age
print(arr)
#运行结果
[('harry', 'male', 40)
('tom', 'male', 31)
('annie', 'female', 14)]
定义数组时,定义不同的names
和formats
,这样,最后得到了结构化的数组,每个元素是一个元组,元组中的三个元素分别是name
,sex
,age
。
这样的数组,保持了原数组的数据的类型。
补充:上面代码中的 U10
表示长度小于10 的字符串,i4
表示占4个字节的整数。
生成结构化数组的关键在于定义不同的数据类型。
定义数据了类型有两种方式:
第一种是用字典,类似上面的示例那样,
dtp = np.dtype(
{"names": ("name", "sex", "age"),
"formats": ("U10", "U10", "i4")}
)
arr = np.zeros(3, dtype=dtp)
arr["name"] = name
arr["sex"] = sex
arr["age"] = age
print(arr)
#运行结果
[('harry', 'male', 40)
('tom', 'male', 31)
('annie', 'female', 14)]
还有一种方式是用元组列表来定义:
dtp = np.dtype([
("name", "U10"),
("sex", "U10"),
("age", "i4")
])
arr = np.zeros(3, dtype=dtp)
arr["name"] = name
arr["sex"] = sex
arr["age"] = age
print(arr)
#运行结果
[('harry', 'male', 40)
('tom', 'male', 31)
('annie', 'female', 14)]
两种方式定义出的结构化数组是一样的。
除了定义上面那种类似excel
表格的二维结构之外,numpy
的数组也能定义跟复杂的结构。
比如定义学生的成绩列表:
dtp = np.dtype([("name", "U10"), ("scores", "f4", (3))])
arr = np.zeros(3, dtype=dtp)
print(arr)
#运行结果
[('', [0., 0., 0.])
('', [0., 0., 0.])
('', [0., 0., 0.])]
arr["name"] = ["harry", "tom", "annie"]
arr["scores"] = [[100, 95.5, 93], [89, 90, 78.5], [77.5, 76, 90]]
print(arr)
#运行结果
[('harry', [100. , 95.5, 93. ])
('tom', [ 89. , 90. , 78.5])
('annie', [ 77.5, 76. , 90. ])]
每个学生对应一个成绩列表,列表中包含3个成绩。
总的来说,numpy
的结构化数组并不常用,对于结构化数组,使用 pandas
库来操作更好。numpy
库一般作为纯数值计算的底层来使用,其实pandas
也是基于 numpy
的。
此外,还有很多其他的python
科学计算的库也是基于numpy
的。