可以在线获取Python Data Scinece Handbook, 章节打开的速度比较慢,可以看一小节的时候,loading另外一个小节。
np.array([range(i , i+3) for i in [1,2,3]])
b = a[::]
print(b)
b[0] = 4
print(a, b)
在上面的代码中,b的元素被修改了,而a却保留了原始值。
x11 = x1[0, 0, ::]
print(x11)
x11 = np.array([0,0,0])
print(x11)
print(x1)
这里x1的值就被x11的value reset所修改了。
x0 = np.arange(1, 10)
x1 = x0.reshape((3,3)) # 注意括号的嵌套
x1.ndim
x1[0,0] = 100
print(x0, x1) # x0的第一个元素已经被修改了
x0并没有因为reshapeg改变维度的个数。但是改变x1的值会相应的改变x0的值。
7. 当需要进行array叠加的时候可以使用concatenate函数,或者vstack和hstack,concatenate通过axis(zero-indexed)控制叠加的方式,axis = 0 相当于vstack(v stands for vertically,顾名思义是垂直叠加),axis = 1 相当于hstack(h stands for horizontally,平行叠加)。通过stack获取的结果变量都是重新create。相对的,split、vsplit、hsplit函数是将一个array按照给定的分割点进行分割。
a = np.array(range(1, 10))
b = np.array(range(2, 11))
c = np.hstack([a,b])
d = np.vstack([a, b])
print(c)
print(d)
# np.hsplit(c, [9])
left, right = np.vsplit(d, [1])
np.split()函数可以对多维数组进行切割,第一个参数是array本身,第二个是integer或者是一个一维的array,当参数为integer时表示将当前array均分成n个子数组,如何分割通过axis进行控制,如果无法进行均等分割的时候,函数会报错。如果参数是一维数组,表示分割点,若超过index,会返回空的subarray。
# numpy的算术操作
a = np.arange(-1, 10, 1)
print(a + 5)
print(a / 5)
print(a ** 2)
print(2 ** np.abs(a)) # 因为a是int,而非float, 所以指数只能是正数
print(a // 10)
print(a - 5)
print(np.abs(a))
print(a % 2)
print(a ** 2 + a + 1)
print(np.exp2(a)) # 指数可以是negative number
# print(np.power(2, a)) # Integers to negative integer powers are not allowed,这是因为a是int,而非float导致的。
# 这都是因为python底层实现导致的,一般而言,np操作的输出数据类型依据的是输入的dtype而不是 output的value,当输入是int,而输出是float的时候
# 底层实现时候选择报错,而没有将结果强制转换为float,which is acceptable.
# 如果将array设置为float类型,则指数为negative number便是可以允许的了
# https://stackoverflow.com/questions/43287311/why-cant-i-raise-to-a-negative-power-in-numpy 有更加详细的解释
# 同时有必要了解下numpy里面的变量类型:https://docs.scipy.org/doc/numpy-1.13.0/user/basics.types.html
# uint8和int8的区别是前者是正整数,后者可以是-整数,同理与uint16\uint32\uint64,位数的不同决定了值的范围。
b = np.arange(-1, 10) # 但是如果增加dtype = 'float',np.power(2, b)可以正常输出
print(np.power(2, b)) # Integers to negative integer powers are not allowed.
print(2 ** b)
print(np.power(-3, np.abs(a)))
print(np.log(a)) # base is e
print(np.log2(np.abs(a)))
print(np.log10(np.abs(a)))
# sometimes 为了保留精度,使用了特殊version的函数来替代raw np.exp and np.log
x = [0, 0.001, 0.01, 0.1]
print("exp(x) - 1 =", np.expm1(x))
print("log(1 + x) =", np.log1p(x))
# 还有很多统计学里面的function可以在scipy.special和numpy里面找到,just search them in the munual book online
对应的output
[ 4 5 6 7 8 9 10 11 12 13 14]
[-0.2 0. 0.2 0.4 0.6 0.8 1. 1.2 1.4 1.6 1.8]
[ 1 0 1 4 9 16 25 36 49 64 81]
[ 2 1 2 4 8 16 32 64 128 256 512]
[-1 0 0 0 0 0 0 0 0 0 0]
[-6 -5 -4 -3 -2 -1 0 1 2 3 4]
[1 0 1 2 3 4 5 6 7 8 9]
[1 0 1 0 1 0 1 0 1 0 1]
[ 1 1 3 7 13 21 31 43 57 73 91]
[5.00e-01 1.00e+00 2.00e+00 4.00e+00 8.00e+00 1.60e+01 3.20e+01 6.40e+01
1.28e+02 2.56e+02 5.12e+02]
[5.00e-01 1.00e+00 2.00e+00 4.00e+00 8.00e+00 1.60e+01 3.20e+01 6.40e+01
1.28e+02 2.56e+02 5.12e+02]
[5.00e-01 1.00e+00 2.00e+00 4.00e+00 8.00e+00 1.60e+01 3.20e+01 6.40e+01
1.28e+02 2.56e+02 5.12e+02]
[ -3 1 -3 9 -27 81 -243 729 -2187 6561
-19683]
[ nan -inf 0. 0.69314718 1.09861229 1.38629436
1.60943791 1.79175947 1.94591015 2.07944154 2.19722458]
[0. -inf 0. 1. 1.5849625 2.
2.32192809 2.5849625 2.80735492 3. 3.169925 ]
[0. -inf 0. 0.30103 0.47712125 0.60205999
0.69897 0.77815125 0.84509804 0.90308999 0.95424251]
exp(x) - 1 = [0. 0.0010005 0.01005017 0.10517092]
log(1 + x) = [0. 0.0009995 0.00995033 0.09531018]
/Users/jiawei/opt/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:25: RuntimeWarning: divide by zero encountered in log
/Users/jiawei/opt/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:25: RuntimeWarning: invalid value encountered in log
/Users/jiawei/opt/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:26: RuntimeWarning: divide by zero encountered in log2
/Users/jiawei/opt/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:27: RuntimeWarning: divide by zero encountered in log10
x = np.arange(1, 10, 2)
y = np.empty(len(x))
np.add(x , x, out = y)
print(y)
z = np.zeros(10)
np.add(x , x, out = z[::2])
print(z)
a = np.arange(1, 10, 1)
print(a)
np.add.reduce(a)
np.add.accumulate(a)
a = np.arange(2, 10, 1, dtype = 'float')
np.divide.reduce(a)
np.divide.accumulate(a)
np.subtract.reduce(a)
np.subtract.accumulate(a)
np.floor_divide.reduce(a)
np.floor_divide.accumulate(a)
np.power.reduce(a)
np.power.accumulate(a)
np.mod.reduce(a)
np.mod.accumulate(a)
print(a)
-- output
[1 2 3 4 5 6 7 8 9]
[2. 3. 4. 5. 6. 7. 8. 9.]
big_data_array = np.arange(1, 100000, 1)
%time sum(big_data_array)
%time np.sum(big_data_array)
# CPU times: user 18.6 ms, sys: 480 µs, total: 19.1 ms
# Wall time: 19.3 ms
# CPU times: user 237 µs, sys: 69 µs, total: 306 µs
# Wall time: 178 µs
%time np.std(big_data_array)
%time np.mean(big_data_array)
%time np.var(big_data_array)
%time np.max(big_data_array)
%time np.min(big_data_array)
%time np.percentile(big_data_array, 25)
# 也可以使用简介版本的syntax,如下:
big_data_array.max()
big_data_array.min()
big_data_array.mean()
big_data_array.std()
big_data_array.var()
big_data_array.sum()
在一些array中可能出现NaN的值,这个时候numpy 1.8之后提供了各种聚集函数的NaN-safe counterpart while ignoring missing values.
# nanargmin and nanargmax are the couterparts of argmin and argmax for the safty of NaN values in the array
np.nanargmax(big_data_array)
np.nanargmin(big_data_array)
np.any(big_data_array)
np.all(big_data_array)
可以通过pandas直接read file,然后转换成array进行处理,不过不知道是否比利用pandas的describe函数要快一些。
import pandas as pd
data = pd.read_csv('data/president_heights.csv')
heights = np.array(data['height(cm)'])
print(heights)
l = [1,2,3]
ind = [1,3]
l[ind]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-162-503a25cf5ab2> in <module>
1 l = [1,2,3]
2 ind = [1,3]
----> 3 l[ind]
TypeError: list indices must be integers or slices, not list
a = np.linspace(-2, 2, 5)
b = np.ones((5))
c = np.multiply.outer(a, b)
print(c[:, 0])
ind = [1,2,3]
print(c[ind])
## output
[-2. -1. 0. 1. 2.]
[[-1. -1. -1. -1. -1.]
[ 0. 0. 0. 0. 0.]
[ 1. 1. 1. 1. 1.]]
numpy.outer(a, b, out=None)[source] Compute the outer product of two vectors.
Parameters:
a : (M,) array_like
First input vector. Input is flattened if not already 1-dimensional.
b : (N,) array_like
Second input vector. Input is flattened if not already 1-dimensional.
out : (M, N) ndarray, optional
A location where the result is stored
New in version 1.9.0.
Returns:
out : (M, N) ndarray
out[i, j] = a[i] * b[j]
fancy indexing可以传二维的数组,而且神奇的是返回数组的shape和传输ind的shape保持一致,而不是原数组。这应该都是和设计这些操作的目的有关系,本身使用这些函数的user就是希望能够取得对应的结果,所以没有必要和原数组的shape保持一致。
rand = np.random.RandomState(0)
x = rand.randint(1000, size = 10)
print(x)
ind = [1,2,3]
print(x[ind])
ind = np.arange(1, 5).reshape(2,2)
print(x[ind])
## output
[684 559 629 192 835 763 707 359 9 723]
[559 629 192] # 原数组是一维,ind也是一维,输出也是一维
[[559 629] # 原数组是一维,ind是二维,输出随着ind的维数变成了二维
[192 835]]
# 关于arange函数,arange(start, end, stop), start和stop可以省略,start默认从0开始,且0 included,step默认是1;
# 如果specify了step那么start就必须要specify。stop是not included in the interval
那fancy indexing如何作用于多维数组呢?
x = np.arange(12).reshape(3, 4)
row = np.array([0, 1, 2])
col = np.array([2, 1, 3])
print('x is shown as follows')
print(x)
print('fancy indexed result:')
print(x[row, col])
# output
x is shown as follows
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
fancy indexed result:
[ 2 5 11]
row和col的维度都是1,所以经过fancy indexing的结果array也是一维的。
**The pairing of indices in fancy indexing follows all the broadcasting rules that were mentioned in Computation on Arrays: Broadcasting. **
在上面的case中,row和col中的元素是一一对应的,但如果在维度不同的case下,就需要了解numpy中的broadcasting的规则。
在前面我们提到可以使用ufunc快速实现numpy的数值计算和统计,从而减少使用无效的loop。broadcasting就是numpy所设计的一组规则用于处理计算时两个array具有不同size的情况。
broadcasting具体的规则
假设我们通过newaxis为row增加了一个维度,则col也需要通过broadcasting的规则对应的进行扩展,最后选择原数组中的元素。
x = np.arange(12).reshape(3, 4)
row = np.array([0, 1, 2])
col = np.array([2, 1, 3])
print('x is shown as follows')
print(x)
print('fancy indexed result:')
print(x[row, col])
y = x[row[:, np.newaxis], col]
print(y)
print('after adding new axis to the row array')
print(x[row[:, np.newaxis], col])
#output
x is shown as follows
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
fancy indexed result:
[ 2 5 11]
[[ 2 1 3]
[ 6 5 7]
[10 9 11]]
after adding new axis to the row array
[[ 2 1 3]
[ 6 5 7]
[10 9 11]]
在work with numpy array时候,我们需要对array进行满足某些条件的分析,例如个数、均值等,甚至是从numpy array中删除一些outliers。Boolean masking可以非常好的完成这些操作。
在numpy中,不仅仅有+,、,*,/这样的ufuncs,而且还实现了<(less than), > (greater than), less than or equal, greater than or equal, not equal(!=), equal(==),这些可以用于element-wise处理但却非常快的ufuncs。这些操作符返回的结果是一个boolen的array(这点很重要,返回结果是布尔数组),as follow examples show:
import numpy as np
a = np.linspace(-1, 10, 10)
print(a)
print(a < 2)
print(a <= 2)
print(a != 2)
print(a == 2)
# Try these comparion opertions on array of multipy dimensions
b = a.reshape(2, 5)
print(b)
# It also works.
print(b <= 2)
对应的output
[-1. 0.22222222 1.44444444 2.66666667 3.88888889 5.11111111
6.33333333 7.55555556 8.77777778 10. ]
[ True True True False False False False False False False]
[ True True True False False False False False False False]
[ True True True True True True True True True True]
[False False False False False False False False False False]
[[-1. 0.22222222 1.44444444 2.66666667 3.88888889]
[ 5.11111111 6.33333333 7.55555556 8.77777778 10. ]]
[[ True True True False False]
[False False False False False]]
当你获得了这些boolen result,仅仅是第一步,numpy提供了很多方便的函数去统计分析这些布尔结果。 那才是你真正想要的。
print(np.sum(a < 2))
print(np.sum(b < 2, axis = 0)) # This counts the number of values less than 2 in each column of the matrix.
print(np.sum(b < 2, axis = 1)) # This counts the number of values less than 2 in each row of the matrix.
# output
3
[1 1 1 0 0]
[3 0]
如果对具体的满足条件的数值不感兴趣,可以使用np.any, np.all来确认是否任何一个或者所有的element都符合你的选择条件。同样,any和all函数也都可以通过axis参数来指定是以每行为单元或每列为单元。
print(np.all(a < 2))
print(np.any(a < 2))
print(np.all(b < 2, axis = 0))
print(np.any(b < 2, axis = 1))
# corresponding results
False
True
[False False False False False]
[ True False]
在上面介绍了单一的选择条件如何实现,而混合选择条件则是现实生活中最常用到的功能。numpy 通过位操作符来达到目的:|, &, ^, ~。这些操作符,numpy重载之后经常用于boolean arrays。^ 是xor,~是非逻辑运算符。
Like with the standard arithmetic operators, NumPy overloads these as ufuncs which work element-wise on (usually Boolean) arrays.
print(np.sum((a < 2) & (a > 100)))
print(np.count_nonzero((a < 2) & (a > 100)))
**注意小括号是必要的,否则结果并不会是你想要的。**因为操作符优先级的问题。
OK,now我们知道如果对这些boolen结果进行统计,那如何从data中选出对应的数据并进行统计分析,使用之前介绍的medain、sum等聚集函数。Let’s look at it. A more powerful pattern is to use Boolean arrays as masks, to select particular subsets of the data themselves.
days = np.arange(365)
summer = (days > 172) & (days < 262)
inches = np.linspace(0, 365, 365)
inche_subset = inches[summer]
np.median(inche_subset)
np.sum(inche_subset)
所以通过boolean operations,mask operations,aggregates operations,可以对手头的数据进行多样的统计分析。经常容易困户的是and opertor and or operator, which are different from & and |。
前者是整个evaluate参与比较的变量,在python中所有非零的数值都是true,所以bool(1 and -10)的结果就是True。但是bitwise操作符号,bool(1 & -10)的结果就是False。
a = np.array([1, 0, 1], dtype = bool)
b = np.array([1, 0, 1], dtype = bool)
a & b # 正常运行
a and b # 会报错
所以在处理boolean array的时候,&和|是经常适合的操作。