数组的裁剪
# 将调用数组中小于和大于下限和上限的元素替换为下限和上限,返回裁剪后的数组,调
# 用数组保持不变。
ndarray.clip(min=下限, max=上限)
数组的压缩
# 返回由调用数组中满足条件的元素组成的新数组。
ndarray.compress(条件)
案例:
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)
np.add(a, a) # 两数组相加
np.add.reduce(a) # a数组元素累加和
np.add.accumulate(a) # 累加和过程
np.add.outer([10, 20, 30], a) # 外和
np.prod(a)
np.cumprod(a)
np.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.divide(a, b) # a 真除 b
np.floor(a / b) # (真除的结果向下取整)
np.ceil(a / b) # (真除的结果向上取整)
np.trunc(a / b) # (真除的结果截断取整)
np.round(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)
位异或:
位异或:
c = a ^ b
c = np.bitwise_xor(a, b)
位与:
e = a & b
e = np.bitwise_and(a, b)
位或:
e = a | b
e = np.bitwise_or(a, b)
位反:
e = ~a
e = np.bitwise_or(a, b)
移位:
<< __lshift__ left_shift
>> __rshift__ right_shift
按位异或操作可以很方便的判断两个数据是否同号。
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])
利用位与运算计算某个数字是否是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)
numpy.sin()
合成方波
一个方波由如下参数的正弦波叠加而成:
y = 4 π × s i n ( x ) y = 4 π 3 × s i n ( 3 x ) . . . . . . y = 4 π 2 n − 1 × s i n ( ( 2 n − 1 ) x ) y = 4\pi \times sin(x) \\ y = \frac{4\pi}{3} \times sin(3x) \\ ...\\ ...\\ y = \frac{4\pi}{2n-1} \times sin((2n-1)x) y=4π×sin(x)y=34π×sin(3x)......y=2n−14π×sin((2n−1)x)
曲线叠加的越多,越接近方波。所以可以设计一个函数,接收曲线的数量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()
对于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()
有一个矩阵M,可以分解为3个矩阵U、S、V,使得U x S x V等于M。U与V都是正交矩阵(乘以自身的转置矩阵结果为单位矩阵)。那么S矩阵主对角线上的元素称为矩阵M的奇异值,其它元素均为0。
import numpy as np
M = np.mat('4 11 14; 8 7 -2')
print(M)
U, sv, V = np.linalg.svd(M, full_matrices=False)
print(U * U.T)
print(V * V.T)
print(sv)
S = np.diag(sv)
print(S)
print(U * S * V)
案例:读取图片的亮度矩阵,提取奇异值与两个正交矩阵,保留部分奇异值,重新生成新的亮度矩阵,绘制图片。
original = sm.imread('../data/lily.jpg', True)
#提取奇异值 sv
U, sv, V = np.linalg.svd(original)
print(U.shape, sv.shape, V.shape)
sv[50:] = 0
original2 = np.mat(U) * np.mat(np.diag(sv)) * np.mat(V)
mp.figure("Lily Features")
mp.subplot(221)
mp.xticks([])
mp.yticks([])
mp.imshow(original, cmap='gray')
mp.subplot(222)
mp.xticks([])
mp.yticks([])
mp.imshow(original2, cmap='gray')
mp.tight_layout()
什么是傅里叶变换?
法国科学家傅里叶提出傅里叶定理,任何一条周期曲线,无论多么跳跃或不规则,都能表示成一组光滑正弦曲线叠加之和。傅里叶变换即是将不规则曲线拆解为一组光滑正弦曲线的过程。
傅里叶变换的目的是可将时域(即时间域)上的信号转变为频域(即频率域)上的信号,随着域的不同,对同一个事物的了解角度也就随之改变,因此在时域中某些不好处理的地方,在频域就可以较为简单的处理。这就可以大量减少处理信号存储量。
例如:弹钢琴
假设有一时间域函数:y = f(x),根据傅里叶的理论它可以被分解为一系列正弦函数的叠加,他们的振幅A,频率ω或初相位φ不同:
y = A 1 s i n ( ω 1 x + ϕ 1 ) + A 2 s i n ( ω 2 x + ϕ 2 ) + A 2 s i n ( ω 2 x + ϕ 2 ) + R y = A_1sin(\omega_1x+\phi_1) + A_2sin(\omega_2x+\phi_2) + A_2sin(\omega_2x+\phi_2) + R y=A1sin(ω1x+ϕ1)+A2sin(ω2x+ϕ2)+A2sin(ω2x+ϕ2)+R
所以傅里叶变换可以把一个比较复杂的函数转换为多个简单函数的叠加,看问题的角度也从时间域转到了频率域,有些的问题处理起来就会比较简单。
导入快速傅里叶变换所需模块
import numpy.fft as nf
通过采样数与采样周期求得傅里叶变换分解所得曲线的频率序列
freqs = np.fft.fftfreq(采样数量, 采样周期)
通过原函数值的序列j经过快速傅里叶变换得到一个复数数组,复数的模代表的是振幅,复数的辐角代表初相位
np.fft.fft(原函数数组) -> 复数数组(表示一组正弦函数)
通过 复数数组 经过逆向傅里叶变换得到合成的函数值数组
np.fft.ifft(复数数组)->原函数值数组
案例:针对方波,绘制时域图与频域图。
import numpy as np
import numpy.fft as nf
import matplotlib.pyplot as mp
times = np.linspace(0, 2 * np.pi, 201)
sigs1 = 4 / (1 * np.pi) * np.sin(1 * times)
sigs2 = 4 / (3 * np.pi) * np.sin(3 * times)
sigs3 = 4 / (5 * np.pi) * np.sin(5 * times)
sigs4 = 4 / (7 * np.pi) * np.sin(7 * times)
sigs5 = 4 / (9 * np.pi) * np.sin(9 * times)
sigs6 = sigs1 + sigs2 + sigs3 + sigs4 + sigs5
mp.subplot(121)
mp.title('Time Domain', fontsize=16)
mp.xlabel('Time', fontsize=12)
mp.ylabel('Signal', fontsize=12)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(times, sigs1, label=r'$\omega$='+str(round(1 / (2 * np.pi),3)))
mp.plot(times, sigs2, label=r'$\omega$='+str(round(3 / (2 * np.pi),3)))
mp.plot(times, sigs3, label=r'$\omega$='+str(round(5 / (2 * np.pi),3)))
mp.plot(times, sigs4, label=r'$\omega$='+str(round(7 / (2 * np.pi),3)))
mp.plot(times, sigs5, label=r'$\omega$='+str(round(9 / (2 * np.pi),3)))
mp.plot(times, sigs6, label=r'$\omega$='+str(round(1 / (2 * np.pi),3)))
mp.legend()
mp.show()
案例:针对合成波做快速傅里叶变换,得到一组复数序列;再针对该复数序列做逆向傅里叶变换得到新的合成波并绘制。
ffts = nf.fft(sigs6)
sigs7 = nf.ifft(ffts).real
mp.plot(times, sigs7, label=r'$\omega$='+str(round(1 / (2 * np.pi),3)), alpha=0.5, linewidth=6)
案例:针对合成波做快速傅里叶变换,得到分解波数组的频率、振幅、初相位数组,并绘制频域图像。
# 得到分解波的频率序列
freqs = nf.fftfreq(times.size, times[1] - times[0])
# 复数的模为信号的振幅(能量大小)
ffts = nf.fft(sigs6)
pows = np.abs(ffts)
mp.subplot(122)
mp.title('Frequency Domain', fontsize=16)
mp.xlabel('Frequency', fontsize=12)
mp.ylabel('Power', fontsize=12)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(freqs[freqs >= 0], pows[freqs >= 0], c='orangered', label='Frequency Spectrum')
mp.legend()
mp.tight_layout()
mp.show()
含噪信号是高能信号与低能噪声叠加的信号,可以通过傅里叶变换的频域滤波实现降噪。
通过FFT使含噪信号转换为含噪频谱,去除低能噪声,留下高能频谱后再通过IFFT留下高能信号。
案例:基于傅里叶变换的频域滤波为音频文件去除噪声。
import numpy as np
import numpy.fft as nf
import scipy.io.wavfile as wf
import matplotlib.pyplot as mp
sample_rate, noised_sigs = wf.read('../data/noised.wav')
noised_sigs = noised_sigs / 2 ** 15
times = np.arange(len(noised_sigs)) / sample_rate
mp.figure('Filter', facecolor='lightgray')
mp.subplot(221)
mp.title('Time Domain', fontsize=16)
mp.ylabel('Signal', fontsize=12)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(times[:178], noised_sigs[:178],c='orangered', label='Noised')
mp.legend()
mp.show()
freqs = nf.fftfreq(times.size, 1 / sample_rate)
noised_ffts = nf.fft(noised_sigs)
noised_pows = np.abs(noised_ffts)
mp.subplot(222)
mp.title('Frequency Domain', fontsize=16)
mp.ylabel('Power', fontsize=12)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.semilogy(freqs[freqs >= 0],noised_pows[freqs >= 0], c='limegreen',label='Noised')
mp.legend()
fund_freq = freqs[noised_pows.argmax()]
noised_indices = np.where(freqs != fund_freq)
filter_ffts = noised_ffts.copy()
filter_ffts[noised_indices] = 0
filter_pows = np.abs(filter_ffts)
mp.subplot(224)
mp.xlabel('Frequency', fontsize=12)
mp.ylabel('Power', fontsize=12)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(freqs[freqs >= 0], filter_pows[freqs >= 0],c='dodgerblue', label='Filter')
mp.legend()
filter_sigs = nf.ifft(filter_ffts).real
mp.subplot(223)
mp.xlabel('Time', fontsize=12)
mp.ylabel('Signal', fontsize=12)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(times[:178], filter_sigs[:178],c='hotpink', label='Filter')
mp.legend()
wf.write('../../data/filter.wav',sample_rate,(filter_sigs * 2 ** 15).astype(np.int16))
生成服从特定统计规律的随机数序列。
二项分布就是重复n次独立事件的伯努利试验。在每次试验中只有两种可能的结果,而且两种结果发生与否互相对立,并且相互独立,事件发生与否的概率在每一次独立试验中都保持不变。
# 产生size个随机数,每个随机数来自n次尝试中的成功次数,其中每次尝试成功的概率为p。
np.random.binomial(n, p, size)
二项分布可以用于求如下场景的概率的近似值:
sum(np.random.binomial(10, 0.3, 200000) == 5) / 200000
sum(np.random.binomial(3, 0.6, 200000) == 0) / 200000
# 产生size个随机数,每个随机数t为在总样本中随机抽取nsample个样本后好样本的个数,总样本由ngood个好样本和nbad个坏样本组成
np.random.hypergeometric(ngood, nbad, nsample, size)
模球游戏:将25个好球和1个坏球放在一起,每次模3个球,全为好球加1分,只要摸到了坏球减6分,求100轮的过程中分值的变化。
import numpy as np
import matplotlib.pyplot as mp
outcomes = np.random.hypergeometric(25, 1, 3, 100)
scores = [0]
for outcome in outcomes:
if outcome == 3:
scores.append(scores[-1] + 1)
else:
scores.append(scores[-1] - 6)
scores = np.array(scores)
mp.figure('Hypergeometric Distribution', facecolor='lightgray')
mp.title('Hypergeometric Distribution', fontsize=20)
mp.xlabel('Round', fontsize=14)
mp.ylabel('Score', fontsize=14)
mp.tick_params(labelsize=12)
mp.grid(linestyle=':')
o, h, l, c = 0, scores.argmax(), scores.argmin(), scores.size-1
if scores[o] < scores[c]:
color = 'orangered'
elif scores[c] < scores[o]:
color = 'limegreen'
else:
color = 'dodgerblue'
mp.plot(scores, c=color, label='Score')
mp.axhline(y=scores[o], linestyle='--',color='deepskyblue', linewidth=1)
mp.axhline(y=scores[h], linestyle='--',color='crimson', linewidth=1)
mp.axhline(y=scores[l], linestyle='--',color='seagreen', linewidth=1)
mp.axhline(y=scores[c], linestyle='--',color='orange', linewidth=1)
mp.legend()
mp.show()
# 产生size个随机数,服从标准正态(期望=0, 标准差=1)分布。
np.random.normal(size)
# 产生size个随机数,服从正态分布(期望=1, 标准差=10)。
np.random.normal(loc=1, scale=10, size)
标 准 正 态 分 布 概 率 密 度 : e − x 2 2 2 π 标准正态分布概率密度: \frac{e^{-\frac{x^2}{2}}}{\sqrt{2\pi}} 标准正态分布概率密度:2πe−2x2
案例:生成10000个服从正态分布的随机数并绘制随机值的频数直方图。
import numpy as np
import matplotlib.pyplot as mp
samples = np.random.normal(size=10000)
mp.figure('Normal Distribution',facecolor='lightgray')
mp.title('Normal Distribution', fontsize=20)
mp.xlabel('Sample', fontsize=14)
mp.ylabel('Occurrence', fontsize=14)
mp.tick_params(labelsize=12)
mp.grid(axis='y', linestyle=':')
mp.hist(samples, 100, normed=True,
edgecolor='steelblue',
facecolor='deepskyblue',
label='Normal')[1]
mp.legend()
mp.show()
联合间接排序
联合间接排序支持为待排序列排序,若待排序列值相同,则利用参考序列作为参考继续排序。最终返回排序过后的有序索引序列。
indices = numpy.lexsort((参考序列, 待排序列))
案例:先按价格排序,再按销售量倒序排列。
import numpy as np
prices = np.array([92,83,71,92,40,12,64])
volumes = np.array([100,251,4,12,709,34,75])
print(volumes)
names = ['Product1','Product2','Product3','Product4','Product5','Product6','Product7']
ind = np.lexsort((volumes*-1, prices))
print(ind)
for i in ind:
print(names[i], end=' ')
复数数组排序
按照实部的升序排列,对于实部相同的元素,参考虚部的升序,直接返回排序后的结果数组。
numpy.sort_complex(复数数组)
插入排序
若有需求需要向有序数组中插入元素,使数组依然有序,numpy提供了searchsorted方法查询并返回可插入位置数组。
indices = numpy.searchsorted(有序数组, 待插入数据数组)
调用numpy提供了insert方法将待插入元素数组中的元素,按照位置数组中的位置,插入到目标数组中,返回结果数组。
numpy.insert(A, indices, B) # 向A数组中的indices位置插入B数组中的元素
案例:
import numpy as np
# 0 1 2 3 4 5 6
a = np.array([1, 2, 4, 5, 6, 8, 9])
b = np.array([7, 3])
c = np.searchsorted(a, b)
print(c)
d = np.insert(a, c, b)
print(d)
需求:统计各小区彩民买彩票的情况:
彩民数量 | 彩票购买量 |
---|---|
30 | 100注 |
40 | 120注 |
50 | 135注 |
60 | 155注 |
45 | - |
65 | 170注 |
scipy提供了常见的插值算法可以通过 一定规律插值器函数。若我们给插值器函数更多的散点x坐标序列,该函数将会返回相应的y坐标序列。
func = si.interp1d(
离散水平坐标,
离散垂直坐标,
kind=插值算法(缺省为线性插值)
)
案例:
# scipy.interpolate
import scipy.interpolate as si
# 原始数据 11组数据
min_x = -50
max_x = 50
dis_x = np.linspace(min_x, max_x, 11)
dis_y = np.sinc(dis_x)
# 通过一系列的散点设计出符合一定规律插值器函数,使用线性插值(kind缺省值)
linear = si.interp1d(dis_x, dis_y)
lin_x = np.linspace(min_x, max_x, 200)
lin_y = linear(lin_x)
# 三次样条插值 (CUbic Spline Interpolation) 获得一条光滑曲线
cubic = si.interp1d(dis_x, dis_y, kind='cubic')
cub_x = np.linspace(min_x, max_x, 200)
cub_y = cubic(cub_x)
直观地说,对于一个给定的正实值函数,在一个实数区间上的定积分可以理解为坐标平面上由曲线、直线以及轴围成的曲边梯形的面积值(一种确定的实数值)。
利用微元法认识什么是积分。
案例:
import numpy as np
import matplotlib.pyplot as mp
import matplotlib.patches as mc
def f(x):
return 2 * x ** 2 + 3 * x + 4
a, b = -5, 5
x1 = np.linspace(a, b, 1001)
y1 = f(x1)
mp.figure('Integral', facecolor='lightgray')
mp.title('Integral', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(x1, y1, c='orangered', linewidth=6,label=r'$y=2x^2+3x+4$', zorder=0)
mp.legend()
mp.show()
n = 50
x2 = np.linspace(a, b, n + 1)
y2 = f(x2)
area = 0
for i in range(n):
area += (y2[i] + y2[i + 1]) * (x2[i + 1] - x2[i]) / 2
print(area)
for i in range(n):
mp.gca().add_patch(mc.Polygon([
[x2[i], 0], [x2[i], y2[i]],
[x2[i + 1], y2[i + 1]], [x2[i + 1], 0]],
fc='deepskyblue', ec='dodgerblue',
alpha=0.5))
调用scipy.integrate模块的quad方法计算积分:
import scipy.integrate as si
# 利用quad求积分 给出函数f,积分下限与积分上限[a, b] 返回(积分值,最大误差)
area = si.quad(f, a, b)[0]
print(area)
scipy.ndimage中提供了一些简单的图像处理,如高斯模糊、任意角度旋转、边缘识别等功能。
import numpy as np
import scipy.misc as sm
import scipy.ndimage as sn
import matplotlib.pyplot as mp
#读取文件
original = sm.imread('../../data/head.jpg', True)
#高斯模糊
median = sn.median_filter(original, 21)
#角度旋转
rotate = sn.rotate(original, 45)
#边缘识别
prewitt = sn.prewitt(original)
mp.figure('Image', facecolor='lightgray')
mp.subplot(221)
mp.title('Original', fontsize=16)
mp.axis('off')
mp.imshow(original, cmap='gray')
mp.subplot(222)
mp.title('Median', fontsize=16)
mp.axis('off')
mp.imshow(median, cmap='gray')
mp.subplot(223)
mp.title('Rotate', fontsize=16)
mp.axis('off')
mp.imshow(rotate, cmap='gray')
mp.subplot(224)
mp.title('Prewitt', fontsize=16)
mp.axis('off')
mp.imshow(prewitt, cmap='gray')
mp.tight_layout()
mp.show()
import numpy as np
# 终值 = np.fv(利率, 期数, 每期支付, 现值)
# 将1000元以1%的年利率存入银行5年,每年加存100元,
# 到期后本息合计多少钱?
fv = np.fv(0.01, 5, -100, -1000)
print(round(fv, 2))
# 现值 = np.pv(利率, 期数, 每期支付, 终值)
# 将多少钱以1%的年利率存入银行5年,每年加存100元,
# 到期后本息合计fv元?
pv = np.pv(0.01, 5, -100, fv)
print(pv)
# 净现值 = np.npv(利率, 现金流)
# 将1000元以1%的年利率存入银行5年,每年加存100元,
# 相当于一次性存入多少钱?
npv = np.npv(0.01, [
-1000, -100, -100, -100, -100, -100])
print(round(npv, 2))
fv = np.fv(0.01, 5, 0, npv)
print(round(fv, 2))
# 内部收益率 = np.irr(现金流)
# 将1000元存入银行5年,以后逐年提现100元、200元、
# 300元、400元、500元,银行利率达到多少,可在最后
# 一次提现后偿清全部本息,即净现值为0元?
irr = np.irr([-1000, 100, 200, 300, 400, 500])
print(round(irr, 2))
npv = np.npv(irr, [-1000, 100, 200, 300, 400, 500])
print(npv)
# 每期支付 = np.pmt(利率, 期数, 现值)
# 以1%的年利率从银行贷款1000元,分5年还清,
# 平均每年还多少钱?
pmt = np.pmt(0.01, 5, 1000)
print(round(pmt, 2))
# 期数 = np.nper(利率, 每期支付, 现值)
# 以1%的年利率从银行贷款1000元,平均每年还pmt元,
# 多少年还清?
nper = np.nper(0.01, pmt, 1000)
print(int(nper))
# 利率 = np.rate(期数, 每期支付, 现值, 终值)
# 从银行贷款1000元,平均每年还pmt元,nper年还清,
# 年利率多少?
rate = np.rate(nper, pmt, 1000, 0)
print(round(rate, 2))