文章目录
  1. 1. numpy
    1. 1.1. 函数与操作符
      1. 1.1.1. ==、>、<、>=、<=
      2. 1.1.2. []
      3. 1.1.3. -/+
      4. 1.1.4. in
      5. 1.1.5. @
      6. 1.1.6. &
      7. 1.1.7. repeat
      8. 1.1.8. ravel
      9. 1.1.9. nonzero
      10. 1.1.10. flatnonzero
      11. 1.1.11. random.seed
      12. 1.1.12. random.choice
      13. 1.1.13. astype
      14. 1.1.14. reshape
      15. 1.1.15. resize
      16. 1.1.16. argsort
      17. 1.1.17. asarray
      18. 1.1.18. where
      19. 1.1.19. log1p
      20. 1.1.20. arange
      21. 1.1.21. logical_and
      22. 1.1.22. corrcoef
      23. 1.1.23. percentile
      24. 1.1.24. split
      25. 1.1.25. array_split
      26. 1.1.26. concatenate
    2. 1.2. 常用方法
      1. 1.2.1. 求众数
  2. 2. matplotlib.pyplot
    1. 2.1. 函数与操作符
      1. 2.1.1. subplot
  3. 3. pandas
    1. 3.1. Effective Pandas
    2. 3.2. DataFrame
      1. 3.2.1. drop
      2. 3.2.2. to Series
    3. 3.3. Series
      1. 3.3.1. loc / iloc
      2. 3.3.2. value_counts
      3. 3.3.3. str.contains
      4. 3.3.4. str.extract
      5. 3.3.5. apply
  4. 4. python
    1. 4.1. 常见用法
      1. 4.1.1. list(range(n))
      2. 4.1.2. list(zip(…))
      3. 4.1.3. dict(zip([…],[…]))
      4. 4.1.4. a[a==a]
      5. 4.1.5. f’abcdefg{a}’

引言:自从发现numpy中的==不返回boolean之后,我觉得学这玩意不能这么简单了。


numpy

这东西真的很像MATLAB,不是吗。显然它重载了各种运算符。

后来才发现numpy的前身是numeric,它确实是一个专门仿MATLAB的库。码农翻身

下面的内容对熟悉面向对象编程的程序员比较友好。

函数与操作符

下面只介绍简单常用用法。

==、>、<、>=、<=

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Visualize some examples from the dataset.
# We show a few examples of training images from each class.
classes = ['plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
num_classes = len(classes)
samples_per_class = 7
for y, cls in enumerate(classes):
result=y_train == y # 解释:y_train{ndarray}[6 9 9 4 1 1 2 7...]
print(type(result),result)# 结果:<class 'numpy.ndarray'> [False False False ... False False False]
idxs = np.flatnonzero(y_train == y)#由于y_train是个一维的,这里也可以写成np.nonzero(y_train==y)[0],见手册flatnonzero
idxs = np.random.choice(idxs, samples_per_class, replace=False)
for i, idx in enumerate(idxs):
plt_idx = i * num_classes + y + 1
plt.subplot(samples_per_class, num_classes, plt_idx)
plt.imshow(X_train[idx].astype('uint8'))
plt.axis('off')
if i == 0:
plt.title(cls)
plt.show()

可以看到ndarray==val后,返回一个相同大小的ndarray,其中所有和val相等的单元变为True,否则变为False。

注:ndarray即多维array,通常使用np.array即可以创建,只是一种类名和叫法。

大于号、小于号、大于等于、小于等于也同理。

[]

np.ndarray的方括号操作符可以传入列表,如

1
2
3
4
>>> a=np.array([1,2,3,4,5,6,7,8,9])
array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a[[2,5,6,7]]
array([3, 6, 7, 8])

也可以使用类似matlab的语法,多维切片:

1
2
3
4
5
6
7
8
>>> a=np.arange(12).reshape(3,4)
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> a[:,1:3]
array([[ 1, 2],
[ 5, 6],
[ 9, 10]])

解释:第一维全选,第二维选择下标[1, 3)

-/+

np.ndarray不仅可以对同维数组进行加减,还可以对维度相差1的数组进行加减。

当维度相差1时,返回的是一个和较高维数组shape相同的数组。

看例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>>> a=np.array(list(range(12))).reshape(3,4)
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> b=np.array(list(range(6,10))).reshape(4)
array([6, 7, 8, 9])
>>> a-b
array([[-6, -6, -6, -6],
[-2, -2, -2, -2],
[ 2, 2, 2, 2]])
>>> b-a
array([[ 6, 6, 6, 6],
[ 2, 2, 2, 2],
[-2, -2, -2, -2]])
>>> a+b
array([[ 6, 8, 10, 12],
[10, 12, 14, 16],
[14, 16, 18, 20]])
>>> b+a
array([[ 6, 8, 10, 12],
[10, 12, 14, 16],
[14, 16, 18, 20]])

特例:

aa1×n1\times nbbm×1m\times1

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
>>> a
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]])
>>> b
array([[0],
[1],
[2],
[3],
[4],
[5],
[6]])
>>> print(a.shape,b.shape)
(1, 12) (7, 1)
>>> a+b
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
[ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
[ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
[ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
[ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
[ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]])

>>> a-b
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
[-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8],
[-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7],
[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6],
[-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]])
>>> b-a
array([[ 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11],
[ 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10],
[ 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9],
[ 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8],
[ 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7],
[ 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6],
[ 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5]])

可以看出无论谁作被减数、减数、加数、被加数,得到的都是7×127\times12 的矩阵。

且可以很容易推断出来,运算规则是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> a.repeat(7,axis=0).shape
(7, 12)
>>> a.repeat(7,axis=0)+b
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
[ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
[ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
[ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
[ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
[ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]])
>>> a.repeat(7,axis=0)-b
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
[-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8],
[-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7],
[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6],
[-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]])

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> b.repeat(12,axis=1).shape
(7, 12)
>>> a+b.repeat(12,axis=1)
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
[ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
[ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
[ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
[ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
[ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]])
>>> a-b.repeat(12,axis=1)
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
[-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8],
[-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7],
[-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6],
[-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]])

意义:如果你有向量an×1a_{n\times 1}bm×1b_{m\times 1},你想得到a、b任意两个维度加减的结果,就可以使用c = a - b.T得到。

那么c[i][j]即a的第i维与b的第j维的差。

相当于

cij=aibjc_{ij}=a_i-b_j

求和同理。

观察可知,应用条件为:

  1. c是个n×mn\times m的矩阵,其中in,jmi\in n,j\in m
  2. a是一个n×1n\times 1的矩阵,即aia_i是一个数值
  3. b是一个m×1m\times 1的矩阵,即bjb_j是一个数值
  4. ccaaii相关,ccbbjj相关,cijc_{ij}aia_ibjb_j的简单加减法得到

特例实操:

需要实现

a.shape=(500, 3072)

b.shape=(5000, 3072)

c = [np.sqrt(np.sum(np.square(a[i] - b), axis=1)) for i in range(a.shape[0])]

c.shape=(500, 5000)

即实现

cij=axis(aibj)2c_{ij}=\sqrt{\sum_{\text{axis}}(a_i-b_j)^2}

求c矩阵。

注意,aia_ibjb_j都是1×30721\times 3072的矩阵。

思想:

由于square、sqrt都是对每个单元进行的,不影响矩阵大小,所以我们可以利用numpy的加法规则绕过最外层的sqrt,即先加后sqrt和先sqrt后加是一样的。

为了利用加法规则,我们改写成

cij=axisai22aibjT+axisbj2c_{ij}=\sqrt{\sum_{\text{axis}}a_i^2-2a_ib_j^T+\sum_{\text{axis}}b_j^2}

之前说了,其中sqrt可以提到外面去,即Cij=axisai22aibjT+axisbj2C_{ij}=\sum_{\text{axis}}a_i^2-2a_ib_j^T+\sum_{\text{axis}}b_j^2,算完之后c=Cc=\sqrt{C}

看到了,aibjTa_ib_j^T很好做,直接矩阵乘法。将选择运算符ii外提,记axisa2\sum_{\text{axis}} a^2AAaxisb2\sum_{\text{axis}}b^2BB,则cc可由AABB的numpy加法得到。为什么选择某行、某列的ii可以外提呢,因为先选择、后平方、求和,以及先平方、求和,后选择,结果是一样的。

代码:

1
2
3
4
5
6
>>> print(a.shape, b.shape)
(500, 3072) (5000, 3072)
>>> A = np.sum(a ** 2, axis=1).reshape(500, 1)
>>> B = np.sum(b ** 2, axis=1).reshape(1, 5000)
>>> C = A + B - 2 * (a @ b.T) # 相同大小矩阵加减
>>> c = np.sqrt(C)

我们做了很多变形,但结果一定是值得的,下面是性能比较:

1
2
Original version took 34.032109 seconds
Pure numpy version took 0.209084 seconds

in

对ndarray使用in时,我们不会得到index,而是得到子数组

1
2
3
4
5
6
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> [i for i in a]
[array([0, 1, 2, 3]), array([4, 5, 6, 7]), array([ 8, 9, 10, 11])]

那么如何获得index呢?

1
2
3
4
5
6
7
8
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> [i for i in range(a.shape[0])]
[0, 1, 2]
>>> [i for i, _ in enumerate(a)] # 不能写作 i in enumerate(a), i会得到一个列表,包含index和value
[0, 1, 2]

@

矩阵乘法matmul可以用@来代替

1
2
3
4
5
6
7
8
9
10
11
import numpy as np

a = np.array([[1, 0], [0, 1]])
b = np.array([[4, 1], [2, 2]])

>>> np.matmul(a, b)
array([[4, 1],
[2, 2]])
>>> a @ b
array([[4, 1],
[2, 2]])

&

ndarray之间的“逻辑运算”只能用&代替,该运算符即“按位与”运算,该运算符的优先级较低,与比较运算符一起用时需要打括号。按位与定义,True与True为True,True与False为False,False与False为False。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> a=np.array(tuple(range(9))).reshape((3,3))
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> b=np.array(list(range(9,0,-1))).reshape([3,3])
array([[9, 8, 7],
[6, 5, 4],
[3, 2, 1]])
>>> (a>=3)&(b>=3)
array([[False, False, False],
[ True, True, True],
[ True, False, False]])
>>> a&b
array([[0, 0, 2],
[2, 4, 4],
[2, 2, 0]])

repeat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> b
array([[0],
[1],
[2],
[3],
[4],
[5],
[6]])
>>> b.shape
(7, 1)
>>> b=b.repeat(10,axis=1)
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[3, 3, 3, 3, 3, 3, 3, 3, 3, 3],
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4],
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5],
[6, 6, 6, 6, 6, 6, 6, 6, 6, 6]])
>>> b.shape
(7, 10)

如果你想使用这种用法,参数axis不可省。

ravel

动词:使纠缠; 使更复杂; 使更纷乱;

名词:纠结之物,拆开部分

拉夫

将ndarray展开,类似于es6和golang中的...运算符。

别看英文示意好像很可怕,实际上我觉得它就是一个展开运算符,多少维的数组都能给你压平。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
np.resize(np.ones(3,dtype=np.int),[3,3,3])
'''
array([[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]],
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]],
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1]]])
'''
np.ravel(a)
# array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])

nonzero

总是返回一个n维数组,通过特殊用法可以列出原n维数组所有非0元素的下标。

1
2
3
4
5
6
7
8
9
10
Examples
--------
>>> x = np.array([[3, 0, 0], [0, 4, 0], [5, 6, 0]])
>>> x
array([[3, 0, 0],
[0, 4, 0],
[5, 6, 0]])
>>> np.nonzero(x)
(array([0, 1, 2, 2]),
array([0, 1, 0, 1]))

再来个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> a=np.array([[[0, 1, 0],
[0, 1, 1],
[1, 0, 1]],
[[1, 1, 1],
[0, 0, 1],
[1, 1, 1]],
[[1, 0, 1],
[0, 1, 1],
[1, 1, 1]]])
>>> a.nonzero() # 用法同np.nonzero(a)
(array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2]),
array([0, 1, 1, 2, 2, 0, 0, 0, 1, 2, 2, 2, 0, 0, 1, 1, 2, 2, 2]),
array([1, 1, 2, 0, 2, 0, 1, 2, 2, 0, 1, 2, 0, 2, 1, 2, 0, 1, 2]))

解释:可以看到返回的结果,第一列就是一个坐标,第二列也是一个坐标,以此类推。

用法:假设有b=np.nonzero(x)

则b这个二维数组意为b[dimension][rank]

假设x是一个三维数组:

np.nonzero(x)[0][0]即第0个非零值的第0维坐标

np.nonzero(x)[1][0]即第0个非零值的第1维坐标

np.nonzero(x)[2][0]即第0个非零值的第2维坐标

那么如何重新访问这个第0个非0值呢?

x[np.nonzero(x)[0][0]][np.nonzero(x)[1][0]][np.nonzero(x)[2][0]]

本例中重复调用了np.nonzero()这个函数,实际上可以保存调用结果,无需多次调用。

flatnonzero

返回一个一位数组,包含传入一维数组中所有非0值的下标

np.flatnonzero(a)np.nonzero(np.ravel(a))[0]

显然由于nonzero返回一个二维数组,而np.ravel返回一个一维数组,那么总是写[0]就显得蠢蠢的,flatnonzero就应运而生了。

一些骚操作比方说:np.flatnonzero(y_train == y)

其中y_train是一个一维数组,y是个值,见手册==一节。

则可找到所有y_train中所有等于y的值的下标。

这里还可以写成np.nonzero(y_train == y)[0],因为不需要ravel。

这个用法很像js中的y_train.filter((v,i)=>v==y&&i),或python中的[i for i,v in enumerate(y_train) if v==y]

至于为什么要喜欢在一位数组上用一个flatnonzero方法,因为numpy是一个类MATLAB的新语言啊(笑)。

random.seed

Random seed used to initialize the pseudo-random number generator. Can be any integer between 0 and 2**32 - 1 inclusive, an array (or other sequence) of such integers, or None (the default). If seed is None, then RandomState will try to read data from /dev/urandom (or the Windows analogue) if available or seed from the clock otherwise.

常常在random.choice之前用。

如果设定一个固定的值,常用于想使得每次运行时随机的结果一致。

random.choice

choice(a, size=None, replace=True, p=None)

def choice(a: Any,
size: Union[int, Iterable, tuple[int], None] = None,
replace: Optional[bool] = True,
p: Any = None) -> Any

Generates a random sample from a given 1-D array

a : 1-D array-like or int
If an ndarray, a random sample is generated from its elements. If an int, the random sample is generated as if a were np.arange(a)
size : int or tuple of ints, optional
Output shape. If the given shape is, e.g., (m, n, k), then m * n * k samples are drawn. Default is None, in which case a single value is returned.
replace : boolean, optional
Whether the sample is with or without replacement
p : 1-D array-like, optional
The probabilities associated with each entry in a. If not given the sample assumes a uniform distribution over all entries in a.
samples : single item or ndarray
The generated random samples
ValueError
If a is an int and less than zero, if a or p are not 1-dimensional, if a is an array-like of size 0, if p is not a vector of probabilities, if a and p have different lengths, or if replace=False and the sample size is greater than the population size

解释:

a

a就是一个样本(sample),可以是int、一维array-like。

其中一维array-like是指一维array、元组这样的结构。

如果是int,则样本为0到n-1。

如果是array-like,则随机出来的值从里面取。

size

从a中抽取几个,即返回值的shape。也可以是一个int,相当于就返回一个一维数组。

如果忽略,只返回一个。

replacement

代表的意思是抽样之后还放不放回去,如果是False的话,那么出来的三个数都不一样,如果是True的话, 有可能会出现重复的,因为前面的抽的放回去了。

replacement在这里的意思是复位(re-placement, 放回),而不是替换。

p

a中每个样本被抽中的概率,默认为等概率。

astype

改变其dtype

常见用法:

1
2
3
4
5
6
>>> a=np.array([[-3,2,3],[4,5,6]], dtype=np.float)
array([[-3., 2., 3.],
[ 4., 5., 6.]])
>>> a.astype(np.uint8) # the same as a.astype('uint8')
array([[253, 2, 3],
[ 4, 5, 6]], dtype=uint8)

一般用法如plt.imshow(X_train[idx].astype(np.uint8)),在显示图片前将其转换到0-255

reshape

将其reshape为新的shape

比方说

1
np.ones(12).reshape((3,4))

限制:新的shape各维乘积必须等于原来shape各维乘积

1
2
>>> np.ones(12).reshape((3,5))
ValueError: cannot reshape array of size 12 into shape (3,5)

骚操作1:某维为-1

由于这种特性,我们有一个骚操作:其中一个数字为-1,numpy就可以帮我们算好该维度该填几

1
2
>>> np.ones(12).reshape((3,-1,2)).shape
(3, 2, 2)

当然,如果你使得最后一个算出来是个小数,显然也是不行的

1
2
>>> np.ones(12).reshape((3,3,-1)).shape
ValueError: cannot reshape array of size 12 into shape (3,3,newaxis)

而且只能有一维是-1

1
2
>>> np.ones(12).reshape((3,-1,-1)).shape
ValueError: can only specify one unknown dimension

骚操作2:flat化

效果等同ravel

1
2
3
4
5
6
7
8
9
10
11
>>> b=np.ones(12).reshape((3,-1,2))
array([[[1., 1.],
[1., 1.]],
[[1., 1.],
[1., 1.]],
[[1., 1.],
[1., 1.]]])
>>> b.reshape(-1)
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
>>> b.ravel()
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])

骚操作3:矩阵转置

这个很简单,就不讲了。

提这个是为了让大家看到reshape可以玩的东西非常多。

resize

resize和reshape相似,但resize可以扩大和缩小数组,无需满足reshape的乘积关系。

扩大数组时,新增的元素填补初始值,如0。

缩小数组时,多余的数组直接舍去。

resize会改变所引用的对象,且无返回值,但reshape返回一个新的对象。

argsort

sort会返回排序好的ndarray

但argsort会返回一个数组的indices

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# https://www.geeksforgeeks.org/sort-sorteda-np-argsorta-np-lexsortb-python/
# Python code to demonstrate working of np.argsort
import numpy as np

# Numpy array created
a = np.array([9, 3, 1, 7, 4, 3, 6])

# unsorted array print
print('Original array:\n', a)

# Sort array indices
b = np.argsort(a)
print('Sorted indices of original array->', b)

# To get sorted array using sorted indices
# c is temp array created of same len as of b
c = np.zeros(len(b), dtype = int)
for i in range(0, len(b)):
c[i]= a[b[i]]
print('Sorted array->', c)
1
2
3
4
5
OUTPUT:np.argsort(a)
Original array:
[9 3 1 7 4 3 6]
Sorted indices of original array-> [2 1 5 4 6 3 0]
Sorted array-> [1 3 3 4 6 7 9]

asarray

将类array转为ndarray

1
2
3
4
>>> a = np.asarray([1,2,3])
array([1, 2, 3])
>>> np.asarray(a)
array([1, 2, 3])

where

numpy.where(condition[, x, y])

Return elements chosen from x or y depending on condition.

condition、x、y是相同shape的类ndarray,其中x和y可以省略(注意,比较运算符的结果也是ndarray)。

当只传入了参数condition,而省略参数x、y的时候,等价于np.asarray(condition).nonzero()

1
2
3
4
5
6
7
8
9
10
11
>>> a=np.array(tuple(range(9))).reshape((3,3))
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> a>5
array([[False, False, False],
[False, False, False],
[ True, True, True]])
>>> np.where(a>5)
(array([2, 2, 2]),
array([0, 1, 2]))

当参数x、y不省略时,相当于c/c++中的三目运算符,condition中某对应元素为True时,对应元素为x中的对应元素,否则为y中的对应元素(注意,非0会转换为True,0转换为False)。

log1p

log1p(x)log(1+x)

For real-valued input, log1p is accurate also for x so small that 1 + x == 1 in floating-point accuracy.

log1p更精确。

1
2
3
4
>>> np.log1p(1e-99)
1e-99
>>> np.log(1 + 1e-99)
0.0

arange

参数含义同python中的range,返回一个1D-array,为np.array(list(range(params)))的缩写。

logical_and

1
2
3
4
5
6
7
>>> a=np.arange(12)
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
>>> b=np.arange(11,-1,-1)
array([11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
>>> np.logical_and(a>3,b>3)
array([False, False, False, False, True, True, True, True, False,
False, False, False])

常常与where或flatnonzero连用:

1
2
3
4
5
6
7
8
9
>>> np.flatnonzero(np.logical_and(a>3,b>3))
array([4, 5, 6, 7])
>>> np.where(np.logical_and(a>3,b>3))
(array([4, 5, 6, 7]),)

>>> a[np.flatnonzero(np.logical_and(a>3,b>3))]
array([4, 5, 6, 7])
>>> a[np.where(np.logical_and(a>3,b>3))]
array([4, 5, 6, 7])

均可取到对应的值。

该函数可被&代替:

1
2
3
>>> (a>3)&(b>3)
array([False, False, False, False, True, True, True, True, False,
False, False, False])

记得加括号。

corrcoef

计算两组数据的协方差,常常用来标定两列数据的相关度。

numpy.corrcoef(x, y=None**,** rowvar=True**,** bias=, ddof=)

Parameters: x : array_like
A 1-D or 2-D array containing multiple variables and observations. Each row of x represents a variable, and each column a single observation of all those variables. Also see rowvar below.

y : array_like, optional
An additional set of variables and observations. y has the same shape as x.

rowvar : bool, optional
If rowvar is True (default), then each row represents a variable, with observations in the columns. Otherwise, the relationship is transposed: each column represents a variable, while the rows contain observations.

bias : _NoValue, optional
Has no effect, do not use.Deprecated since version 1.10.0.

ddof : _NoValue, optionalHas no effect, do not use.Deprecated since version 1.10.0.
Returns: R : ndarray
The correlation coefficient matrix of the variables.

percentile

输入1D-array A,百分比B%,返回给一个阈值C,使得集合{a  aA, aC}\{a~|~\forall a \in A,~a\leqslant C\}的元素个数是集合A的B%。

1
2
3
4
5
6
>>> np.percentile([1,2,3,4,5,6,7,8,9,10],20)
2.8000000000000003
>>> np.percentile([1,2,3,4,5,6,7,8,9,10],50)
5.5
>>> np.percentile([1,2,3,4,5,6,7,8,9,10],100)
10.0

split

numpy.split(ary, indices_or_sections**,** axis=0)

Split an array into multiple sub-arrays.

将数组划分为若干个等长子数组,如果无法等长,则raise error。

1
2
3
4
>>> np.split(np.asarray([1,2,3,4,5,6,7,8]),3)
ValueError: array split does not result in an equal division
>>> np.array_split(np.arange(9),3)
[array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]

indices_or_sections

如果是个整数n,则分为n组。

如果是个1-D like array,则是若干个分界点。

1
2
>>> np.array_split(np.arange(9),[5,6])
[array([0, 1, 2, 3, 4]), array([5]), array([6, 7, 8])]

显然,分为[:5],[5:6],[6:]

array_split

numpy.array_split(ary, indices_or_sections**,** axis=0)

Split an array into multiple sub-arrays.

将一个数组划分为尽可能等长的多个子数组,如果不可能,则最后几个子数组就少一点。

交叉验证时常用。

1
2
3
4
>>> np.array_split(np.asarray([1,2,3,4,5,6,7,8]),3)
[array([1, 2, 3]), array([4, 5, 6]), array([7, 8])]
>>> np.array_split(np.arange(7),5)
[array([0, 1]), array([2, 3]), array([4]), array([5]), array([6])]

indices_or_sections

见split一节。

concatenate

numpy.concatenate((a1, a2, …), axis=0, out=None)

1
2
3
4
5
6
7
8
9
10
11
12
>>> np.concatenate([[1,2,3],[7,8,9],[4,5,6]])
array([1, 2, 3, 7, 8, 9, 4, 5, 6])
>>> a=np.array([[1,2],
[3,4]])
>>> b=np.array([[5,6]])
>>> np.concatenate([a,b],axis=0)
array([[1, 2],
[3, 4],
[5, 6]])
>>> np.concatenate([a,b.T],axis=1)
array([[1, 2, 5],
[3, 4, 6]])

拼合数组

常用方法

求众数

在numpy中没有直接的方法,但是也可以这样实现:

1
2
3
4
5
6
7
import numpy as np

#counts的index即该数,counts的值即该数出现的次数
counts = np.bincount(nums)

#返回该众数
index = np.argmax(counts)

该方法在获取众数的时候会返回最小的众数。

下面方法会返回最靠前的众数:

1
2
3
4
5
6
7
8
9
10
11
import numpy as np
from collections import Counter

nums=[1,1,2,2,3,3,4]
#返回该众数
Counter(nums).most_common(1)[0][0]
#返回该众数的次数
Counter(nums).most_common(1)[0][1]
#返回两个众数
Counter(nums).most_common(2)
Out: [(1,2),(2,2)]

看一下Counter是什么:

1
2
3
>>> from collections import Counter
>>> Counter([1,3,2,4,5,3,3,2,2])
Counter({3: 3, 2: 3, 1: 1, 4: 1, 5: 1})

可以看到,Counter会先按次数排,次数相同按出现顺序排,即Counter使用了一个顺序稳定的排序。

matplotlib.pyplot

这应该是matlab的plot的python实现吧。

函数与操作符

下面只介绍简单常用用法。

subplot

https://morvanzhou.github.io/tutorials/data-manipulation/plt/4-1-subpot1/

pandas

Effective Pandas

Effective Pandas

DataFrame

drop

DataFrame.drop(self, labels=None, axis=0, index=None, columns=None, level=None, inplace=False, errors=‘raise’)[source]

Drop specified labels from rows or columns.

Remove rows or columns by specifying label names and corresponding axis, or by specifying directly index or column names. When using a multi-index, labels on different levels can be removed by specifying the level.

Parameters: labels : single label or list-likeIndex or column labels to drop.

axis : {0 or ‘index’, 1 or ‘columns’}, default 0Whether to drop labels from the index (0 or ‘index’) or columns (1 or ‘columns’).

index : single label or list-likeAlternative to specifying axis (labels, axis=0 is equivalent to index=labels).*New in version 0.21.0.

*columns : single label or list-likeAlternative to specifying axis (labels, axis=1 is equivalent to columns=labels).New in version 0.21.0.

level : int or level name, optionalFor MultiIndex, level from which the labels will be removed.

inplace : bool, default FalseIf True, do operation inplace and return None.

errors : {‘ignore’, ‘raise’}, default ‘raise’If ‘ignore’, suppress error and only existing labels are dropped.
Returns: DataFrameDataFrame without the removed index or column labels.
Raises: KeyErrorIf any of the labels is not found in the selected axis.

drop one row

1
2
3
4
5
6
7
8
9
10
11
>>> a=pd.DataFrame(np.arange(12,0,-1).reshape((3,4)),index=["a","b","c"],columns=["A","B","C","D"])
A B C D
a 12 11 10 9
b 8 7 6 5
c 4 3 2 1
>>> a.drop("a")
A B C D
b 8 7 6 5
c 4 3 2 1
# the same as a.drop("a",axis="rows")
# the same as a.drop("a",axis=0)

drop one column

1
2
3
4
5
6
7
8
9
10
11
12
>>> a=pd.DataFrame(np.arange(12,0,-1).reshape((3,4)),index=["a","b","c"],columns=["A","B","C","D"])
A B C D
a 12 11 10 9
b 8 7 6 5
c 4 3 2 1
>>> a.drop(columns="A")
B C D
a 11 10 9
b 7 6 5
c 3 2 1
# the same as a.drop("A",axis="columns")
# the same as a.drop("A",axis=1)

同时drop某行和某列是不被允许的。

drop multi-rows / multi-columns

1
2
3
4
5
6
7
8
9
10
>>> a=pd.DataFrame(np.arange(12,0,-1).reshape((3,4)),index=["a","b","c"],columns=["A","B","C","D"])
A B C D
a 12 11 10 9
b 8 7 6 5
c 4 3 2 1
>>> a.drop(columns=["A","C"])
B D
a 11 9
b 7 5
c 3 1

inplace

1
2
3
4
5
6
7
8
9
10
11
>>> a=pd.DataFrame(np.arange(12,0,-1).reshape((3,4)),index=["a","b","c"],columns=["A","B","C","D"])
A B C D
a 12 11 10 9
b 8 7 6 5
c 4 3 2 1
>>> a.drop("a",inplace=True)
(no output and a has changed)
>>> a
A B C D
b 8 7 6 5
c 4 3 2 1

to Series

Series其实就是某列啦

使用loc或iloc就可以了

Series

Series 是带标签的一维数组,可存储整数、浮点数、字符串、Python 对象等类型的数据。轴标签统称为索引。调用 pd.Series 函数即可创建 Series:

1
>>> s = pd.Series(data, index=index)

上述代码中,data 支持以下数据类型:

  • Python 字典
  • 多维数组
  • 标量值(如,5)

index 是轴标签列表。

loc / iloc

loc[x]取得索引index(key)为x的value

iloc[x]取得第x个value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> a=pd.Series(np.arange(12,0,-1),index=range(1,24,2))
1 12
3 11
5 10
7 9
9 8
11 7
13 6
15 5
17 4
19 3
21 2
23 1
dtype: int64
>>> a.loc[3]
11
>>> a.iloc[3]
9

value_counts

def value_counts(self, normalize=False, sort=True, ascending=False,

​ bins=None, dropna=True):

Parameters

----------

normalize : boolean, default False

​ If True then the object returned will contain the relative frequencies of the unique values.

sort : boolean, default True

​ Sort by values

ascending : boolean, default False

​ Sort in ascending order

bins : integer, optional

​ Rather than count values, group them into half-open bins, a convenience for pd.cut, only works with numeric data

dropna : boolean, default True

​ Don’t include counts of NaN.

常规用法

1
2
3
4
5
6
7
8
>>> a=pd.Series([5,1,2,3,1,2,3,1,1,2]).value_counts()
1 4
2 3
3 2
5 1
dtype: int64
>>> type(a)
pandas.core.series.Series

normalize

1
2
3
4
5
6
>>> pd.Series([5,1,2,3,1,2,3,1,1,2]).value_counts(normalize=True)
1 0.4
2 0.3
3 0.2
5 0.1
dtype: float64

可以看到出现频率被归一化了。

str.contains

Series.str.contains(self, pat, case=True, flags=0, na=nan, regex=True)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>> test=pd.Series(['Mouse', 'dog', 'house and parrot', '23', math.nan])
>>> test.str.contains('oG|ou', case=True, regex=True)
0 True
1 False
2 True
3 False
4 NaN
dtype: object
>>> test.str.contains('oG', case=True, regex=True, na='WhateverYouWant')
0 False
1 False
2 False
3 False
4 WhateverYouWant
dtype: object

str.extract

Series.str.extract(self, pat, flags=0, expand=True)

正则并分列

1
2
3
4
5
6
7
8
>>> test=pd.Series(['yes:a','yes:c','abc'])
>>> res=test.str.extract('yes:(.*)')
0
0 a
1 c
2 NaN
>>> type(res)
<class 'pandas.core.frame.DataFrame'>
1
2
3
4
5
6
>>> test=pd.Series(['yes:a','yes:c','abc'])
>>> res=test.str.extract('(.*):(.*)')
0 1
0 yes a
1 yes c
2 NaN NaN

expand

default: True

1
2
3
4
5
6
7
8
>>> test=pd.Series(['yes:a','yes:c','abc'])
>>> res=test.str.extract('yes:(.*)',expand=False)
0 a
1 c
2 NaN
dtype: object
>>> type(res)
<class 'pandas.core.series.Series'>

为True:结果扩展为DataFrame。

为False:如果分组只有一列,则结果为Series或Index,否则结果为DataFrame。

apply

映射

1
2
3
4
5
pd.Series(['3','4','5']).apply(lambda x:int(x))
0 3
1 4
2 5
dtype: int64

返回一个新对象,不会改变原有对象。

python

常见用法

list(range(n))

将range类型转换为list

如list(range(10))即相当于[x for x in range(10)]

1
2
3
4
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [x for x in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

list(zip(…))

和函数名字一样,它就是个拉链。

1
2
3
4
5
6
>>> print(list(zip([1,2,3])))
[(1,), (2,), (3,)]
>>> print(list(zip([1,2,3],[4,5,6])))
[(1, 4), (2, 5), (3, 6)]
>>> print(list(zip([1,2,3],[4,5,6],[7,8,9])))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]

看到这里,是不是有点感觉了?

我们再配合*来让它表现更明显:

注:*的作用是将列表展开

1
2
3
4
5
6
>>> print(list(zip(*[[1,2,3],
[4,5,6],
[7,8,9]])))
[(1, 4, 7),
(2, 5, 8),
(3, 6, 9)]

它将一个二维列表转置了(上述输入输出经过了处理,使其更加形象)。

dict(zip([…],[…]))

该方法常常用于将两个数组映射到一个dict。

1
2
3
4
>>> dict(zip([1,2,3],[4,5,6]))
{1: 4, 2: 5, 3: 6}
>>> dict(zip([1,"appolo",3],["yeah",5,True]))
{1: 'yeah', 'appolo': 5, 3: True}

a[a==a]

常用于numpy和pandas,去除NaN项

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> import math
>>> import pandas as pd
>>> a=pd.Series([1,2,3,math.nan,4,5])
>>> a[a==a]
0 1.0
1 2.0
2 3.0
4 4.0
5 5.0
>>> import numpy as np
>>> a=np.array([1,2,3,math.nan,4,5])
>>> a[a==a]
array([1., 2., 3., 4., 5.])

f’abcdefg{a}’

类似es6的`abcdefg${a}`

1
2
3
4
5
6
7
>>> a='!!!!!!!yes you are right!!!'
>>> b='ok'
>>> print(f'abcdefg{a}{b}???')
abcdefg!!!!!!!yes you are right!!!ok???
>>> print('abcdefg%s%s???'%(a,b))
abcdefg!!!!!!!yes you are right!!!ok???
>>> print('abcdefg{}{}???'.format(a,b))
1
2
3
4
5
6
>>> '{:.3f}'.format(1)
'1.000'
>>> f'{1:.3f}'
'1.000'
>>> '%.3f'%1
'1.000'
文章目录
  1. 1. numpy
    1. 1.1. 函数与操作符
      1. 1.1.1. ==、>、<、>=、<=
      2. 1.1.2. []
      3. 1.1.3. -/+
      4. 1.1.4. in
      5. 1.1.5. @
      6. 1.1.6. &
      7. 1.1.7. repeat
      8. 1.1.8. ravel
      9. 1.1.9. nonzero
      10. 1.1.10. flatnonzero
      11. 1.1.11. random.seed
      12. 1.1.12. random.choice
      13. 1.1.13. astype
      14. 1.1.14. reshape
      15. 1.1.15. resize
      16. 1.1.16. argsort
      17. 1.1.17. asarray
      18. 1.1.18. where
      19. 1.1.19. log1p
      20. 1.1.20. arange
      21. 1.1.21. logical_and
      22. 1.1.22. corrcoef
      23. 1.1.23. percentile
      24. 1.1.24. split
      25. 1.1.25. array_split
      26. 1.1.26. concatenate
    2. 1.2. 常用方法
      1. 1.2.1. 求众数
  2. 2. matplotlib.pyplot
    1. 2.1. 函数与操作符
      1. 2.1.1. subplot
  3. 3. pandas
    1. 3.1. Effective Pandas
    2. 3.2. DataFrame
      1. 3.2.1. drop
      2. 3.2.2. to Series
    3. 3.3. Series
      1. 3.3.1. loc / iloc
      2. 3.3.2. value_counts
      3. 3.3.3. str.contains
      4. 3.3.4. str.extract
      5. 3.3.5. apply
  4. 4. python
    1. 4.1. 常见用法
      1. 4.1.1. list(range(n))
      2. 4.1.2. list(zip(…))
      3. 4.1.3. dict(zip([…],[…]))
      4. 4.1.4. a[a==a]
      5. 4.1.5. f’abcdefg{a}’