符号数组
sign函数可以把样本数组的变成对应的符号数组,正数变为1,负数变为-1,0则变为0。
ary = np.sign(源数组)
净额成交量(OBV)
成交量可以反映市场对某支股票的人气,而成交量是一只股票上涨的能量。一支股票的上涨往往需要较大的成交量。而下跌时则不然。
若相比上一天的收盘价上涨,则为正成交量;若相比上一天的收盘价下跌,则为负成交量。
绘制OBV柱状图
dates, closing_prices, volumes = np.loadtxt(
'../../data/bhp.csv', delimiter=',',
usecols=(1, 6, 7), unpack=True,
dtype='M8[D], f8, f8', converters={1: dmy2ymd})
diff_closing_prices = np.diff(closing_prices)
sign_closing_prices = np.sign(diff_closing_prices)
obvs = volumes[1:] * sign_closing_prices
mp.figure('On-Balance Volume', facecolor='lightgray')
mp.title('On-Balance Volume', fontsize=20)
mp.xlabel('Date', fontsize=14)
mp.ylabel('OBV', fontsize=14)
ax = mp.gca()
ax.xaxis.set_major_locator(md.WeekdayLocator(byweekday=md.MO))
ax.xaxis.set_minor_locator(md.DayLocator())
ax.xaxis.set_major_formatter(md.DateFormatter('%d %b %Y'))
mp.tick_params(labelsize=10)
mp.grid(axis='y', linestyle=':')
dates = dates[1:].astype(md.datetime.datetime)
mp.bar(dates, obvs, 1.0, color='dodgerblue',
edgecolor='white', label='OBV')
mp.legend()
mp.gcf().autofmt_xdate()
mp.show()
数组处理函数
ary = np.piecewise(源数组, 条件序列, 取值序列)
针对源数组中的每一个元素,检测其是否符合条件序列中的每一个条件,符合哪个条件就用取值系列中与之对应的值,表示该元素,放到目标 数组中返回。
条件序列: [a < 0, a == 0, a > 0]
取值序列: [-1, 0, 1]
a = np.array([70, 80, 60, 30, 40])
d = np.piecewise(
a,
[a < 60, a == 60, a > 60],
[-1, 0, 1])
# d = [ 1 1 0 -1 -1]
矢量化
矢量化指的是用数组代替标量来操作数组里的每个元素。
numpy提供了vectorize函数,可以把处理标量的函数矢量化,返回的函数可以直接处理ndarray数组。
import math as m
import numpy as np
def foo(x, y):
return m.sqrt(x**2 + y**2)
x, y = 1, 4
print(foo(x, y))
X, Y = np.array([1, 2, 3]), np.array([4, 5, 6])
vectorized_foo = np.vectorize(foo)
print(vectorized_foo(X, Y))
print(np.vectorize(foo)(X, Y))
numpy还提供了frompyfuc函数,也可以完成与vectorize相同的功能:
# 把foo转换成矢量函数,该矢量函数接收2个参数,返回一个结果
fun = np.frompyfunc(foo, 2, 1)
fun(X, Y)
案例:定义一种买进卖出策略,通过历史数据判断这种策略是否值得实施。
dates, opening_prices, highest_prices, \
lowest_prices, closing_prices = np.loadtxt(
'../../data/bhp.csv', delimiter=',',
usecols=(1, 3, 4, 5, 6), unpack=True,
dtype='M8[D], f8, f8, f8, f8',
converters={1: dmy2ymd})
# 定义一种投资策略
def profit(opening_price, highest_price,
lowest_price, closing_price):
buying_price = opening_price * 0.99
if lowest_price <= buying_price <= highest_price:
return (closing_price - buying_price) * \
100 / buying_price
return np.nan # 无效值
# 矢量化投资函数
profits = np.vectorize(profit)(opening_prices,
highest_prices, lowest_prices, closing_prices)
nan = np.isnan(profits)
dates, profits = dates[~nan], profits[~nan]
gain_dates, gain_profits = dates[profits > 0], profits[profits > 0]
loss_dates, loss_profits = dates[profits < 0], profits[profits < 0]
mp.figure('Trading Simulation', facecolor='lightgray')
mp.title('Trading Simulation', fontsize=20)
mp.xlabel('Date', fontsize=14)
mp.ylabel('Profit', fontsize=14)
ax = mp.gca()
ax.xaxis.set_major_locator(md.WeekdayLocator(byweekday=md.MO))
ax.xaxis.set_minor_locator(md.DayLocator())
ax.xaxis.set_major_formatter(md.DateFormatter('%d %b %Y'))
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
if dates.size > 0:
dates = dates.astype(md.datetime.datetime)
mp.plot(dates, profits, c='gray',
label='Profit')
mp.axhline(y=profits.mean(), linestyle='--',
color='gray')
if gain_dates.size > 0:
gain_dates = gain_dates.astype(md.datetime.datetime)
mp.plot(gain_dates, gain_profits, 'o',
c='orangered', label='Gain Profit')
mp.axhline(y=gain_profits.mean(), linestyle='--',
color='orangered')
if loss_dates.size > 0:
loss_dates = loss_dates.astype(md.datetime.datetime)
mp.plot(loss_dates, loss_profits, 'o',
c='limegreen', label='Loss Profit')
mp.axhline(y=loss_profits.mean(), linestyle='--',
color='limegreen')
mp.legend()
mp.gcf().autofmt_xdate()
mp.show()
矩阵
矩阵是numpy.matrix类类型的对象,该类继承自numpy.ndarray,任何针对多维数组的操作,对矩阵同样有效,但是作为子类矩阵又结合其自身的特点,做了必要的扩充,比如:乘法计算、求逆等。
矩阵对象的创建
# 如果copy的值为True(缺省),所得到的矩阵对象与参数中的源容器各自拥有独立的数据拷贝。
numpy.matrix(
ary, # 任何可被解释为矩阵的二维容器
copy=True # 是否复制数据(缺省值为True,即复制数据)
)
# 等价于:numpy.matrix(..., copy=False)
# 由该函数创建的矩阵对象与参数中的源容器一定共享数据,无法拥有独立的数据拷贝
numpy.mat(任何可被解释为矩阵的二维容器)
# 该函数可以接受字符串形式的矩阵描述:
# 数据项通过空格分隔,数据行通过分号分隔。例如:'1 2 3; 4 5 6'
numpy.mat(拼块规则)
矩阵的乘法运算
# 矩阵的乘法:乘积矩阵的第i行第j列的元素等于
# 被乘数矩阵的第i行与乘数矩阵的第j列的点积
#
# 1 2 6
# X----> 3 5 7
# | 4 8 9
# |
# 1 2 6 31 60 74
# 3 5 7 46 87 116
# 4 8 9 64 120 161
e = np.mat('1 2 6; 3 5 7; 4 8 9')
print(e * e)
矩阵的逆矩阵
若两个矩阵A、B满足:AB = BA = E (E为单位矩阵),则成为A、B为逆矩阵。
e = np.mat('1 2 6; 3 5 7; 4 8 9')
print(e.I)
print(e * e.I)
ndarray提供了方法让多维数组替代矩阵的运算:
a = np.array([
[1, 2, 6],
[3, 5, 7],
[4, 8, 9]])
# 点乘法求ndarray的点乘结果,与矩阵的乘法运算结果相同
k = a.dot(a)
print(k)
# linalg模块中的inv方法可以求取a的逆矩阵
l = np.linalg.inv(a)
print(l)
案例:假设一帮孩子和家长出去旅游,去程坐的是bus,小孩票价为3元,家长票价为3.2元,共花了118.4;回程坐的是Train,小孩票价为3.5元,家长票价为3.6元,共花了135.2。分别求小孩和家长的人数。使用矩阵求解。
$$
\left[ \begin{array}{ccc}
3 & 3.2 \
3.5 & 3.6 \
\end{array} \right]
\times
\left[ \begin{array}{ccc}
x \
y \
\end{array} \right]
\left[ \begin{array}{ccc}
118.4 \
135.2 \
\end{array} \right]
$$
import numpy as np
prices = np.mat('3 3.2; 3.5 3.6')
totals = np.mat('118.4; 135.2')
persons = prices.I * totals
print(persons)
案例:斐波那契数列
1 1 2 3 5 8 13 21 34 …
X 1 1 1 1 1 1
1 0 1 0 1 0
--------------------------------
1 1 2 1 3 2 5 3
1 0 1 1 2 1 3 2
F^1 F^2 F^3 F^4 ... f^n
代码
import numpy as np
n = 35
# 使用递归实现斐波那契数列
def fibo(n):
return 1 if n < 3 else fibo(n - 1) + fibo(n - 2)
print(fibo(n))
# 使用矩阵实现斐波那契数列
print(int((np.mat('1. 1.; 1. 0.') ** (n - 1))[0, 0]))
通用函数
数组的裁剪
# 将调用数组中小于和大于下限和上限的元素替换为下限和上限,返回裁剪后的数组,调
# 用数组保持不变。
ndarray.clip(min=下限, max=上限)
数组的压缩
# 返回由调用数组中满足条件的元素组成的新数组。
ndarray.compress(条件)
数组的累乘
# 返回调用数组中所有元素的乘积——累乘。
ndarray.prod()
# 返回调用数组中所有元素执行累乘的过程数组。
ndarray.cumprod()
案例:
from __future__ import unicode_literals
import numpy as np
a = np.array([10, 20, 30, 40, 50])
print(a)
b = a.clip(min=15, max=45)
print(b)
c = a.compress((15 <= a) & (a <= 45))
print(c)
d = a.prod()
print(d)
e = a.cumprod()
print(e)
def jiecheng(n):
return n if n == 1 else n * jiecheng(n - 1)
n = 5
print(jiecheng(n))
jc = 1
for i in range(2, n + 1):
jc *= i
print(jc)
print(np.arange(2, n + 1).prod())
加法通用函数
add(a, a) # 两数组相加
add.reduce(a) # a数组元素累加和
add.accumulate(a) # 累加和过程
add.outer([10, 20, 30], a) # 外和
案例:
a = np.arange(1, 7)
print(a)
b = a + a
print(b)
b = np.add(a, a)
print(b)
c = np.add.reduce(a)
print(c)
d = np.add.accumulate(a)
print(d)
# + 1 2 3 4 5 6
# --------------------
# 10 |11 12 13 14 15 16 |
# 20 |21 22 23 24 25 26 |
# 30 |31 32 33 34 35 36 |
--------------------
f = np.add.outer([10, 20, 30], a)
print(f)
# x 1 2 3 4 5 6
# -----------------------
# 10 |10 20 30 40 50 60 |
# 20 |20 40 60 80 100 120 |
# 30 |30 60 90 120 150 180 |
-----------------------
g = np.outer([10, 20, 30], a)
print(g)
除法通用函数
np.true_divide(a, b) # a 真除 b (对应位置相除)
np.divide(a, b) # a 真除 b
np.floor_divide(a, b) # a 地板除 b (真除的结果向下取整)
np.ceil(a / b) # a 天花板除 b (真除的结果向上取整)
np.trunc(a / b) # a 截断除 b (真除的结果直接干掉小数部分)
案例:
import numpy as np
a = np.array([20, 20, -20, -20])
b = np.array([3, -3, 6, -6])
# 真除
c = np.true_divide(a, b)
c = np.divide(a, b)
c = a / b
print('array:',c)
# 对ndarray做floor操作
d = np.floor(a / b)
print('floor_divide:',d)
# 对ndarray做ceil操作
e = np.ceil(a / b)
print('ceil ndarray:',e)
# 对ndarray做trunc操作
f = np.trunc(a / b)
print('trunc ndarray:',f)
# 对ndarray做around操作
g = np.around(a / b)
print('around ndarray:',g)
三角函数通用函数
numpy.sin()
合成方波
一个方波由如下参数的正弦波叠加而成:
曲线叠加的越多,越接近方波。所以可以设计一个函数,接收曲线的数量n作为参数,返回一个矢量函数,该函数可以接收x坐标数组,返回n个正弦波叠加得到的y坐标数组。
x = np.linspace(-2*np.pi, 2*np.pi, 1000)
y = np.zeros(1000)
n = 1000
for i in range(1, n+1):
y += 4 / ((2 * i - 1) * np.pi) * np.sin((2 * i - 1) * x)
mp.plot(x, y, label='n=1000')
mp.legend()
mp.show()
位运算通用函数
位异或:
c = a ^ b
c = a.__xor__(b)
c = np.bitwise_xor(a, b)
按位异或操作可以很方便的判断两个数据是否同号。
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
a = np.array([0, -1, 2, -3, 4, -5])
b = np.array([0, 1, 2, 3, 4, 5])
print(a, b)
c = a ^ b
# c = a.__xor__(b)
# c = np.bitwise_xor(a, b)
print(np.where(c < 0)[0])
位与:
e = a & b
e = a.__and__(b)
e = np.bitwise_and(a, b)
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
利用位与运算计算某个数字是否是2的幂
# 1 2^0 00001 0 00000
# 2 2^1 00010 1 00001
# 4 2^2 00100 3 00011
# 8 2^3 01000 7 00111
# 16 2^4 10000 15 01111
# ...
d = np.arange(1, 21)
print(d)
e = d & (d - 1)
e = d.__and__(d - 1)
e = np.bitwise_and(d, d - 1)
print(e)
位或:
|
__or__
bitwise_or
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
位反:
~
__not__
bitwise_not
~0 = 1
~1 = 0
移位:
<< __lshift__ left_shift
>> __rshift__ right_shift
左移1位相当于乘2,右移1位相当于除2。
d = np.arange(1, 21)
print(d)
# f = d << 1
# f = d.__lshift__(1)
f = np.left_shift(d, 1)
print(f)
特征值和特征向量
对于n阶方阵A,如果存在数a和非零n维列向量x,使得Ax=ax,则称a是矩阵A的一个特征值,x是矩阵A属于特征值a的特征向量
#已知n阶方阵A, 求特征值与特征数组
# eigvals: 特征值数组
# eigvecs: 特征向量数组
eigvals, eigvecs = np.linalg.eig(A)
#已知特征值与特征向量,求方阵
S = np.mat(eigvecs) * np.mat(np.diag(eigvals)) * np.mat(eigvecs逆)
案例:
import numpy as np
A = np.mat('3 -2; 1 0')
print(A)
eigvals, eigvecs = np.linalg.eig(A)
print(eigvals)
print(eigvecs)
print(A * eigvecs[:, 0]) # 方阵*特征向量
print(eigvals[0] * eigvecs[:, 0]) #特征值*特征向量
S = np.mat(eigvecs) * np.mat(np.diag(eigvals)) * np.mat(eigvecs.I)
案例:读取图片的亮度矩阵,提取特征值与特征向量,保留部分特征值,重新生成新的亮度矩阵,绘制图片。
'''
特征值与特征向量
'''
import numpy as np
import scipy.misc as sm
import matplotlib.pyplot as mp
original = sm.imread('../data/lily.jpg', True)
#提取特征值
eigvals, eigvecs = np.linalg.eig(original)
eigvals[50:] = 0
print(np.diag(eigvals).shape)
original2 = np.mat(eigvecs) * np.mat(np.diag(eigvals)) * np.mat(eigvecs).I
mp.figure("Lily Features")
mp.subplot(121)
mp.xticks([])
mp.yticks([])
mp.imshow(original, cmap='gray')
mp.subplot(122)
mp.xticks([])
mp.yticks([])
mp.imshow(original2, cmap='gray')
mp.tight_layout()
mp.show()