numpy入门

参考w3cschool numpy tutorial(基本上就是照着翻译,然后加入自己的理解,顺便把代码结果附上,over)

数组

可以将list tuple直接通过array()转化成ndarray

1
2
3
4
5
6
7
import numpy as np

arr = np.array([1, 2, 3, 4, 5]) // arr = np.array((1, 2, 3, 4, 5))

printf(arr)

printf(type(arr))

numpy的数组存在维度,当然python可以通过list嵌套实现,但是并不是真正意义上的数组,肯定没有这个快,而且没有现成的方法

可以通过x.ndim方法来检查数组的维度

前面提到可以通过np.array()来转化一个数组,后面可以跟一个参数ndim来显示的指定维度(不显示地指定ndim的参数的话,会根据传入的list..的维度来决定数组的维度)

1
2
3
4
arr = np.array([1, 2, 3, 4], ndmin=5)
print(arr)

res: [[[[[1 2 3 4]]]]]

既然都是数组了,那肯定支持下标索引,但是这里的索引有所差异,一般我们的索引都是这样的arr[3][2][1]这样的,但是在numpy里面,需要arr[3,2,1]这样访问。

1
2
3
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr[1, 2])
res: 6

同样支持负数索引

1
2
3
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr[1, -1])
res: 6

同样支持索引,这里表示得到arr下标为1的位置的元素,并拿其从0到1(左闭右开)的元素,形成一个数组

1
2
3
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr[1, 0:1])
res: [4]

后面同样可以跟步长

1
2
3
4
5
6
7
arr = np.array([1, 2, 3, 4, 5, 6, 7])
print(arr[::2])
res: [1 3 5 7]

arr = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
print(arr[1, 1:4])
res: [7, 8, 9]

####数据类型
#####python的数据类型:字符串,整数,浮点数,布尔数,复数

#####numpy的数据类型:

1
2
3
4
5
6
7
8
9
10
11
i - integer
b - boolean
u - unsigned integer 无符号整型
f - float
c - complex float 复数浮点数
m - timedelta
M - datetime 日期时间
O - object 对象
S - string
U - unicode string 采用unicode编码的字符串
V - fixed chunk of memory for other type ( void ) void

可以在np.array()里面显示的调用类型声明,如果声明有误,比如是字符串,后面跟了一个dtype=’i’,就会报错

i,u,f,S 可以定义大小

1
2
3
4
5
arr = np.array([1, 2, 3, 4], dtype='i4')  #四个字节 一个字节八位
print(arr)
print(arr.dtype)
res: [1 2 3 4]
int32

#####数组类型转化
通过数组的astype(‘类型’)方法来进行copy

1
2
3
4
5
6
7
arr = np.array([1.1, 2.1, 3.1])
newarr = arr.astype('i')
newarr[0] = 10
print(newarr)
print(arr)
res: [10 2 3]
[1.1 2.1 3.1]

里面的参数可以写完整一点:int、bool 这样都是可识别的

#####视图和拷贝的区别
类似浅拷贝和深拷贝的关系
view:视图,也就是浅拷贝,修改这个值,会连带修改它的原主人,同样,修改原主人也会影响view,连坐

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
arr = np.array([1, 2, 3, 4, 5])
x = arr.view()
arr[0] = 42
print(arr)
print(x)
res: [42 2 3 4 5]
[42 2 3 4 5]

arr = np.array([1, 2, 3, 4, 5])
x = arr.view()
x[0] = 31
print(arr)
print(x)
res: [31 2 3 4 5]
[31 2 3 4 5]

copy: 拷贝,深拷贝,独立的一份

tips:view有一个属性base:原数组,copy没有,修改base就是修改原数组,同样会引起view的改变

1
2
3
4
5
6
7
8
9
10
11
arr = np.array([1, 2, 3, 4, 5])
x = arr.copy()
y = arr.view()
y[0] = 2
print(x.base)
print(y.base)
print(type(y.base))
print(y)
y.base[0] = 0
print(arr)
print(y)

####shape方法
前面提到 ndim方法(和ndim一样,后面没有括号,应该是属性,习惯说成方法),可以拿到数组的维度,这里的shape方法则会返回更加具体,会返回每个维度的在当前维度元素的个数(返回的是元组)

1
2
3
4
5
6
7
8
9
10
11
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
print(type(arr.shape))
print(arr.shape)
res: <class 'tuple'>
(2, 4)

arr = np.array([1, 2, 3, 4], ndmin=5)
print(arr)
print('shape of array :', arr.shape)
res: [[[[[1 2 3 4]]]]]
shape of array : (1, 1, 1, 1, 4)

####reshape方法
顾名思义就是改变维度,但是reshape需要维度对应,不能随意改变维度,比如一维有十二个元素,满足二维的3 * 4,那么就可以改变,但是不满足就不能改变,比如2 * 5

1
2
3
4
5
6
7
8
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
newarr = arr.reshape(4, 3)
print(newarr)
res:
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]

而且reshape返回的是原数组的view,里面有base属性,修改会造成连坐
tips:可以使用unknown dimension,如果你有某一个维度不知道里面具体有多少元素,那么你可以在reshape里面写一个-1,numpy为为你自动计算(前提是可以算出来)

如果reshape里面的参数是-1,则会将数组展成一维数组

1
2
3
4
arr = np.array([[1, 2, 3], [4, 5, 6]])
newarr = arr.reshape(-1)
print(newarr)
res:[1 2 3 4 5 6 7 8]

####数组迭代
1、经典for循环,拿到的是最外层数组里面的元素(里面的n-1维数组),可以接着套娃,处理高维数据比较复杂

1
2
3
4
5
6
7
8
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
for x in arr:
print(x)
res:
[[1 2 3]
[4 5 6]]
[[ 7 8 9]
[10 11 12]]

2、np.nditer(arr)迭代每一个元素

1
2
3
4
5
6
7
8
9
10
11
12
arr = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
for x in np.nditer(arr):
print(x)
res:
1
2
3
4
5
6
7
8

在这个迭代中,我们可以传一个op_dtypes的参数来修改数组中元素的值的类型,op->操作,dtypes->类型,但是呢,并不能直接在数组中操作,规定要再传一个参数,flags=[‘buffered’]表示在一个额外的空间buffer里进行操作,龟腚。

1
2
3
4
5
6
7
8
9
10
11
arr = np.array([1, 2, 3])
for x in np.nditer(arr, flags=['buffered'], op_dtypes=['S']):
print(x)
print(type(x))
res:
b'1'
<class 'numpy.ndarray'>
b'2'
<class 'numpy.ndarray'>
b'3'
<class 'numpy.ndarray'>

tips:自python更新到3.0后,dtype类型中’S’被修改为 (byte-)string类型,所以输出含b指的是此字符串类型为byteString类,有点搞

然后,这个参数arr同样支持切片(包括步长)

1
2
3
4
5
6
7
8
arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
for x in np.nditer(arr[:, ::2]):
print(x)
res:
1
3
5
7

3、enumerate,python原来自带有一个enumerate,可以返回list、tuple和string的下标和对应元素,同样的,numpy里也有一个ndenumerate,使用方法类似enumerate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
arr = np.array([1, 2, 3])
for idx, x in np.ndenumerate(arr):
print(idx, x)
res:
(0,) 1 #这个如果不是idx,x,直接是x的话,拿到的是一个tuple
(1,) 2 #这里的idx同样是一个tuple
(2,) 3

arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
for idx, x in np.ndenumerate(arr):
print(idx, x)
res: #如果是高维的,同样是挨个遍历
(0, 0) 1
(0, 1) 2
(0, 2) 3
(0, 3) 4
(1, 0) 5
(1, 1) 6
(1, 2) 7
(1, 3) 8

感觉别人有点盛气凌人,是我的错觉吗,一定要学会控制自己的情绪,一定要抱持冷静客观,喷人是解决不了问题的(可能会爽)QAQ 也许是最近压力太大造成的,好好休息吧