Numpy
Numpy是科学计算基础库,提供大量科学计算相关功能,比如数据统计,随机数生成等。其提供最核心类型为多维数组类型(ndarray)。numpy支持向量处理ndarray对象,提高程序运算速度。
ndarray:n-dimensional array object,任意维数的数组对象
Numpy http://www.numpy.org/
1、使用方式
安装numpy库 pip install numpy 使用numpy库 import numpy as np
2、数组创建
Numpy提供很多函数创建数组,常用函数如下:
- array
- arange
- ones/ones_like
- zeros/zeros_like
- empty/empty_like
- full/full_like
- eye/identity
- linspace
- logspace
导入numpy模块
import numpy as np
Ipython中的 In 和 Out
# In :Ipython解释器提供特殊对象,用来存储输入信息,列表类型
# Out :Ipython解释器提供特殊对象,用来存储输出信息,字典类型。当单元格运行后,最后一个表达式非空的时候,将信息保存到out对象
# np.__version__ # 查看版本号
# print(np.__version__)
In
array()方法
# 使用array方法创建一维数组,传入参数为列表
# n = np.array([1,2,3])
# # 注意:对于display()方法,python解释器不支持,ipython解释器才支持。
# display(n)
# print(n)
# 使用array创建多维数组,传入参数是嵌套列表
n= np.array([[1,2],[3,4]])
display(n)
arange方法
# arange方法类似python中range方法,传入参数也包含起始值,结束值和步长
# n = np.arange(10)
# n = np.arange(1,10)
# n=np.arange(1,10,2)
# n
# 步长可以是浮点型,以及负数
n = np.arange(3,1,-0.5)
n
ones 和 ones_like
# ones(shape,dtype=None,order='C')创建全为1的数组
# shape 整型或者元祖
# dtype 数据类型 默认numpy.float64
n1 = np.ones(3)
display(n1)
n2 = np.ones((3,4))
display(n2)
np.ones((3,2))
# ones_like:根据传入的数组形状创建全为1的数组
n3 = np.ones_like(n2)
display(n3)
zeros 和 zeros_like
# zeros方法创建全为0的数组
n1 = np.zeros(3)
display(n1)
n2 = np.zeros((3,4))
display(n2)
# zeros_like:根据传入的数组形状创建全为0的数组
n3 = np.zeros_like(n2)
display(n3)
empty 和 empty_like
# empty创建全为空数组:注意,数据并不是设置为0,而是值未初始化,需要我们自己来初始化
n1 = np.ones(3)
n1 = None
n1 = np.empty(3)
display(n1)
# empty_like 根据传入的数组形状创建全为空的数组
n2 = np.empty_like(n1)
display(n2)
full 和 full_like
# full(shape,fill_value) 创建全为某个指定数据的数组
# shape 数组维度或者形状
# fill_value 指定数据
n1 = np.full((2,2),3)
display(n1)
# full_like:根据传入数组形状创建数组,同时指定全为某个数
n2 = np.full_like(n1,4)
display(n2)
eye和identity
# eye和identity创建单位矩阵
n1 = np.eye(3)
display(n1)
n2 = np.identity(3)
display(n2)
linspace
# linspace根据一定间隔创建等差数组
# 格式:np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
# 1,2,3,4,5
# endpoint=True 间隔 end-start/(num-1)
n1 = np.linspace(1,5,num=5)
display(n1)
# 1,2,3...50
n2 = np.linspace(1,50)
display(n2)
# endpoint=False 间隔 end-start/num
# 5-1/5 4/5 0.8
# 1 1.8 2.6 3.4 4.2
n3 = np.linspace(1,5,num=5,endpoint=False)
display(n3)
logspace
# logspace根据指数函数创建等比数组
# 格式:np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
# 1 2 4 8
n1 = np.logspace(0,3,num=4,base=2)
display(n1)
# 1 10 100 1000
n2 = np.logspace(0,3,num=4)
display(n2)
3、数组ndarray和列表(List)比较
优势
- 数组可与标量进行计算,数组之间可进行向量化计算
- 数组在运算时,具有广播能力。
- 数组底层使用c语言编写,运行速度快
- 数组底层使用c数组的存储方式,节省内存空间
# 班上同学的python成绩,统一加1分
# 列表操作
scores = [90,91,92]
# 循环遍历列表
for i in range(len(scores)):
scores[i]+=1
display(scores)
# 数组操作
scores_ndarray = np.array([90,91,92])
# 整体操作,不再需要循环遍历
scores_ndarray+=1
display(scores_ndarray)
a = np.array([1,2,3,4])
b = np.array([[1,1,1],[2,2,2]])
display(a+b)
4、魔法命令
魔法命令是ipython提供特殊命令,能实现一些特殊功能,比如统计时间(time/timeit)和占用内存(memit/mprun)等功能。 魔法命令两种形式:
- % :行模式
- %% :单元格模式
time
time 统计语句执行时间,被统计语句只执行一次
timeit
timeit可以循环多次执行被统计语句,得到平均执行时间,支持行模式和单元格模式。 timeit命令参数,–n 指定每轮测试次数,-r 指定测试轮数(默认为7) 单元格模式
- 第一行语句(与timeit同一行语句)为初始化语句,作用为后续代码中变量提供初始化功能。
- 初始化语句每轮测试只执行一次,且不参与计时。第二行至整个单元格末尾语句会执行相应次数,并参与计时。
# 统计time.sleep(0.5)语句执行时间
import time
start = time.time()
time.sleep(0.5)
end = time.time()
display(end-start)
# time用来统计语句执行时间,被统计语句只执行一次
%time time.sleep(0.5)
%time a=1
# 46.1 ns ± 2.75 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
# 7 runs 运行7轮
# 10000000 loops 每轮循环执行次数
# 46.1 ns ± 2.75 ns per loop (mean ± std 均值是46.1 标准差是2.75 ns 【46.1 ns - 2.75,46.1 ns + 2.75】
%timeit a=1
# -n 每轮循环的次数
# -r 执行轮数 默认是7轮
%timeit -n 1000 -r 2 a=1
%%time
time.sleep(0.5)
time.sleep(0.6)
%%timeit -n 2 -r 2
time.sleep(0.5)
time.sleep(0.6)
%%timeit -n 2 -r 3 print('初始化语句')
print('hello world')
# 单元格模式下,我们可以在timeit后面(同一行)使用初始化语句
# 初始化语句作用为后续被统计的执行代码提供变量的初始化
# 初始化语句执行次数由轮数来决定
%%timeit li = list(range(100000))
# 第一行作为初始化语句,不参与计时 操作
# 对列表的+1操作,多行,故timeit使用单元格模式
for i in range(len(li)):
li[i]+=1
%%timeit a = np.arange(100000)
# 1ms=1000us
a+=1
writefile
将单元格内容写入到文件中。如果文件不存在则创建,如果文件存在,则覆盖文件。如果指定 –a 参数,则追加内容,不覆盖。
%%writefile test.py # 文件不存在则创建
x=1
print(x)
print("hello world!")
%%writefile test.py # 文件存在,则覆盖
print('update....')
%%writefile -a test.py # 指定 –a 参数,则追加
print('update222222....')
执行结果:
Appending to test.py
run
运行外部python文件,运行结束后,外部文件中定义的变量得到保留。 格式: %run 文件路径
前提准备:在jupyter 主目录下(与 魔法命令 run所在的numpy.ipynb目录一致)新建一个 test.py 的文件,里面包含代码如下
a=1
print(a)
print("hello world!")
在 numpy.ipynb 中:
%run test.py
执行结果:
1 hello world
再次执行下面语句:
In [22]:(输入)
a
Out[22]:(输出)
1
memit
分析语句内存使用情况。memit支持行模式与单元格模式。单元格模式下,初始化语句不会参与计算内存。第二行至整个单元格末尾会参与计算内存。 说明:
- memit不是Ipython内置,需要安装memory_profiler模块(pip install memory_profiler)
- 安装后,需要通过%load_ext memory_profiler载入,才能使用
载入
%load_ext memory_profiler
def m1():
print('hello world')
%memit m1()
运行结果:
hello world hello world hello world hello world peak memory: 52.05 MiB, increment: 0.14 MiB
对单个语句使用:
%memit x=2
运行结果:
peak memory: 67.02 MiB, increment: 0.00 MiB
mprun
逐行分析语句内存使用情况,分析结果列如下:
- Line 行号
- Mem usage 内存使用大小
- increment内存增量
- Line content 代码内容
说明:
- mprun不是Ipython内置,需要安装memory_profiler模块
- 安装后,需要通过%load_ext memory_profiler载入,才能使用
- mprun测试的函数必须定义在独立模块中,不能定义在交互式Ipython环境中
- 如果需要重新加载模块,可以调用importlib模块提供reload函数实现
%%writefile test2.py
def m():
li1 = [i for i in range(20000)]
li2 = [i for i in range(400000)]
执行结果:
Overwriting test2.py
%load_ext memory_profiler
执行结果:
The memory_profiler extension is already loaded. To reload it, use: %reload_ext memory_profiler
In [25]:
# import test2
# 修改代码后,想要再次导入代码所在的模块成功,需要使用importlib模块的relaod方法
import importlib
importlib.reload(test2)
Out[25]:
In [26]:
# %mprun -f 分析函数 执行语句
%mprun -f test2.m test2.m()
4、数组属性
数组对象具有如下常用属性:
- ndim:n-dimension,维度
- shape:形状,每个维度上相应长度
- dtype::数据类型
- size:数组元素个数
- itemsize:一个数组元素占用内存空间,字节为单位
In [7]:
x = np.array([1,2,3])
display(x.ndim)
y = np.array([[1,2,3],[2,3,4]])
display(y.ndim)
# 返回数组对象形状,每个维度上长度,元祖
display(y.shape)
# 返回数据类型
display(y.dtype)
# 返回元素个数
display(y.size)
# 返回一个元素占用内存空间,字节为单位
display(y.itemsize)
执行结果:
1
2
(2,3)
dtype('int32')
6
4
5、数据类型及转换
- 创建数组时候,可使用dtype指定数组中元素类型
- 如果没有指定,根据元素类型进行推断
- 如果类型不同,会选择兼容类型
- 使用astype函数转换数据类型
In [13]:
# 使用dtype指定数组中元素类型
x = np.array([1,2,3],dtype=np.float32)
display(x.dtype)
# 如果没有指定,根据元素类型进行推断
y = np.array([1.1,2.1,3.1])
display(y.dtype)
# 如果类型不同,会选择兼容类型(向上)
z = np.array([1.1,2,3,4])
display(z.dtype)
# 使用astype函数转换数据类型
w = np.array([1.1,2.2,3.3,-4.4])
display(w.dtype)
m = w.astype(np.int64)
display(m)
执行结果:
dtype('float32')
dtype('float64')
dtype('float64')
dtype('float64')
array([ 1, 2, 3, -4], dtype=int64)
6、改变数组形状
我们可以通过数组对象的reshape方法(或者np的reshape函数)改变数组形状。 说明:
- nump中很多方法,既可以使用np来访问,也可以通过数组对象来访问
# 一维数组改为多维数组
x = np.arange(6)
display(x)
# 数组对象,reshape的参数可以是元祖,也可以将元祖中内容分开传入
# y=x.reshape(3,2)
# np的reshape方法,只能使用元祖传入,不能将元祖中内容分开传入
y=np.reshape(x,3,2)
display(y)
# 多维数组改为1维数组
# x = np.array([[1,2,3],[3,4,5]])
# display(x)
# # y = x.reshape((-1))
# y = np.reshape(x,(-1))
# display(y)
7、索引与切片
在python中,序列类型支持索引与切片。ndarray数组也支持类似操作。不过两者之间既有相同点,也有不同点。
- 相似点:数组对象也支持索引与切片,语法python中索引与切片类似
- 不同点:数组切片返回的原数组数据视图。如果需要复制底层数组元素,可使用数组对象copy方法 注意:视图共享底层数组元素。
In [25]:
# 索引访问
x = np.arange(9).reshape(3,3)
display(x)
# 从低维获取数据
# x是2维数组,包含低维和高维,低维对应向下坐标轴,表示为0方向;高维对应向右 坐标轴,表示1方向。
# x[1]从低维度,也就是从0方向上获取数据,即访问的第一行的数据
display(x[1])
display(x[1][1])
执行结果:
array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
array([3, 4, 5])
4
# 切片访问
# 0 1 2
# 3 4 5
# 6 7 8
x = np.arange(9).reshape(3,3)
display(x)
# 得到
# 3 4 5
# 6 7 8
# y = x[1:3]
# display(y)
# 得到
# 3 4
# 6 7
# y = x[1:3,0:2]
# display(y)
# 得到
# 1 2
# 4 5
# 7 8
# y = x[:,1:3]
# display(y)
# 得到
# 1 2
# 4 5
# y = x[0:2,1:3]
# display(y)
# 得到 修改步长
# 0 1 2
# 6 7 8
y = x[0:3:2,:]
display(y)
执行结果:
array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
array([[0, 1, 2], [6, 7, 8]])
# 切片得到新的数组,和原有的数组共享底层内存中数据,修改其中一方都会去影响对方的数据
# 通过数组对象的copy方法得到新的数组,新的数组和原有数组之间不共享数据
x = np.array([1,2,3])
# y = x[:]
# # y[0]=100
# x[0]=200
# display(x)
# display(y)
w = x.copy()
w[0]=30
display(x)
display(w)
执行结果:
array([1, 2, 3])
array([30, 2, 3])
# 对列表切片操作,使用的浅拷贝,修改新的列表不会影响原有的列表
li = [1,2,3]
li2 = li[:]
li2[0] = 10
display(li)
display(li2)
执行结果:
[1, 2, 3]
[10, 2, 3]
8、整数数组进行索引
当选取元素不连续时候,可以提供一个索引数组选择(或修改)对应索引位置元素。 说明
- 通过整数数组索引,返回的是原数组拷贝
- 可以提供多个一维数组索引,此时会将每个数组中内容对应作为索引,返回对应的元素
In [57]:
x = np.arange(20).reshape(5,4)
display(x)
# 获取第0 2 3,不连续数据
# y = x[[0,2,3]]
# display(y)
# y[0][0]=100
# display(y)
# display(x)
# 返回0 (0,0) 2 (0,2) 8 (2,0)10 (2,2)
# [0,0,2,2] [0,2,0,2]
y= x[[0,0,2,2],[0,2,0,2]]
display(y)
执行结果:
array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18, 19]])
array([ 0, 2, 8, 10])
9、布尔数组进行索引
我们可通过布尔数组对数组进行索引,获取对应的元素。获取数据原则,为True,获取对应位置,为False,不获取。 说明:
- 索引布尔数组通过对现有数组计算得到
- 逻辑运算符和python不同:and->&, or->|,not->~,条件组合时候,条件需用小括号
x = np.arange(12).reshape(4,3)
display(x)
# 使用布尔数组获取第0行 1行数据
y=x[[True,True,False,False]]
display(y)
# 大于5
# x[x>5]
# 大于1小于5数据返回
x[(x>1) & (x<5)]
执行结果:
array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11]])
array([[0, 1, 2], [3, 4, 5]])
Out[26]:
array([2, 3, 4])
10、数组扁平化
我们可以通过调用ravel或flatten方法,对数组对象进行扁平化处理
- np.ravel/ravel
- flatten 两者区别在于,ravel返回数组原数组共享数据,而flatten返回原数组拷贝
In [33]:
x = np.arange(12).reshape(3,2,2)
display(x)
# y = np.ravel(x)
# 返回的数组和原数组共享数据,修改返回数组影响原有数组
y=x.ravel()
y[0]=200
# 返回的原数组拷贝,修改返回数组不影响原有数组
# y = x.flatten()
# y[0] = 100
display(x)
display(y)
执行结果:
array([[[ 0, 1],
[ 2, 3]],
[[ 4, 5],
[ 6, 7]],
[[ 8, 9],
[10, 11]]])
array([[[200, 1],
[ 2, 3]],
[[ 4, 5],
[ 6, 7]],
[[ 8, 9],
[ 10, 11]]])
array([200, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
11、数组存储顺序
在创建数组时,我们可以通过order参数指定数组元素存储顺序。存储顺序分为2种:
- C: 按照行存储
- F: 按照列存储 说明:order参数作用于两个步骤:一是数据抽取(扁平化处理)顺序;二是数据构建(数组填充)顺序
x = np.array([1,2,3,4]).reshape((2,2),order='C')
y = np.array([1,2,3,4]).reshape((2,2),order='F')
display(x)
display(y)
执行结果:
array([[1, 2], [3, 4]])
array([[1, 3], [2, 4]])
x = np.array([[1,2],[3,4]]).reshape((2,2),order='C')
y = np.array([[1,2],[3,4]]).reshape((2,2),order='F')
display(x)
display(y)
执行结果:
array([[1, 2], [3, 4]])
array([[1, 2], [3, 4]])
结果说明:order()函数的数据作用过程,作用于两步:1.扁平化处理;2.数据构建。
12、通用函数ufunc(universal function)
Numpy提供很多通用函数,它们可看做对应Python计算向量化版本
- abs/fabs
- cell/floor
- exp
- log/log2/log10
- modf
- sin/sinh/cos/cosh
- sqrt
In [16]:
x = np.array([-1.2,10,1.5])
display(x)
# np.abs(x)
np.modf(x)
执行结果:
array([ -1.2, 10. , 1.5])
Out[16]:
(array([-0.2, 0. , 0.5]), array([ -1., 10., 1.]))
13、统计函数
Numpy具有如下常用统计函数
- mean/sum
- max/min
- argmax/argmin
- std/var
- cumsum/cumprod
# 统计函数如果只传入数组对象的话,它会对数组首先做一个扁平化处理,再对扁平化后的一维数组的所有的数据进行统计
x = np.arange(1,5).reshape(2,2)
display(x)
# display(np.mean(x),np.sum(x))
# display(np.max(x),np.min(x))
# argmax 得到最大值对应索引值,argmin最小值对应索引值
# display(np.argmax(x),np.argmin(x))
# std标准差 var方差
# display(np.std(x),np.var(x))
# cumsum 累加和 cumprod 累乘
display(np.cumsum(x),np.cumprod(x))
执行结果:
array([[1, 2],
[3, 4]])
array([ 1, 3, 6, 10], dtype=int32)
array([ 1, 2, 6, 24], dtype=int32)
14、轴(axis)
可以指定axis参数改变统计的轴。在二维数组中,0表示竖直方向操作,1表示沿着水平方向操作。 超过二维的多维数组,轴相对复杂,可认为沿着轴所指定坐标变化方向,其他轴坐标不变。进行操作。比如轴是0,则根据第0个坐标变化方向
1、为什么统计函数需要传入axis参数 2、如何理解axis,特别数组维度超过2维时候。例如:学生成绩表格如下
| 姓名 | 语文 | 数学 | | ---- | ---- | ---- | | 张三 | 90 | 94 | | 李四 | 85 | 100 |
scores = np.array([[90,92],[85,100]])
# axis=0,从竖直方向统计数据,获得语文的最高分,以及数学的最高分
display(np.max(scores,axis=0))
# 如果我们指定轴为0,第一个维度的坐标变化的,第二个维度的坐标不变
运行结果:
array([ 90, 100])
x = np.arange(12).reshape((3,2,2))
display(x)
display(x.sum(axis=0))
运行结果:
array([[[ 0, 1],
[ 2, 3]],
[[ 4, 5],
[ 6, 7]],
[[ 8, 9],
[10, 11]]])
array([[12, 15],
[18, 21]])
15、连接和拆分函数
- np.concatenate对多个数组按指定轴方向进行连接
- np.vstack/np.hstack
- np.split/np.hsplit/np.vsplit
101班成绩 .
| 数学 | 语文 | | ---- | ---- | | 95 | 100 | | 96 | 98 |
102班成绩 .
| 数学 | 语文 | | ---- | ---- | | 97 | 98 | | 96 | 99 | | 95 | 94 |
101班成绩 数学 语文 [[95,100], [96,98]]
102班成绩 数学 语文 [[97,98], [96,99], [95,94]]
# 对101班和102班成绩进行垂直连接,列数一致
x = np.array([[95,100],
[96,98]])
y = np.array( [[97,98],
[96,99],
[95,94]])
# display(x,y)
# w = np.concatenate((x,y),axis=0)
w = np.vstack((x,y))
display(w)
# 对w进行横向切分,将数据切分2部分
# z = np.split(w,2,axis=1)
# display(z)
# 对w进行纵向切分,得到3部分数据 第0,1行,第2,3行 第4行
z = np.split(w,[2,4],axis=0)
display(z)
运行结果:
array([[ 95, 100],
[ 96, 98],
[ 97, 98],
[ 96, 99],
[ 95, 94]])
[array([[ 95, 100],
[ 96, 98]]), array([[97, 98],
[96, 99]]), array([[95, 94]])]
101班成绩 数学 语文 [[95,100], [96,98]]
101班 身高 体重 [[175,65], [177,70]] 175 65 177 70
# 对101班zs和ls成绩和身高及体重数据水平连接,保证行数一致
x = np.array([[95,100],
[96,98]])
y = np.array( [[175,65],
[177,70]])
display(x,y)
# w = np.concatenate((x,y),axis=1)
w = np.hstack((x,y))
display(w)
# 对w进行纵向切分
z = np.split(w,2,axis=0)
display(z)
运行结果:
array([[ 95, 100],
[ 96, 98]])
array([[175, 65],
[177, 70]])
array([[ 95, 100, 175, 65],
[ 96, 98, 177, 70]])
[array([[ 95, 100, 175, 65]]), array([[ 96, 98, 177, 70]])]
16、其他函数
- any/all
- transpose
- dot
- np.sort
- np.argsort
In [103]:
# any和all运算时,数组元素为0 False 空返回False,其他返回True
# any有一个数组元素返回True,any返回True
x = np.array([0,0,False])
display(x.any(),x.all())
运行结果:
False
False
In [109]:
# transpose对数组数据进行装置
x = np.arange(1,5).reshape(2,2)
display(x)
# display(x.transpose())
display(x.T)
# 数组转置本质上轴的颠倒,对于二维数组a[i][j]-->a[j][ip] a[0][1]-->a[1][0]
# 传入参数,指定轴的颠倒顺序
y = np.arange(1,13).reshape(3,2,2)
# display(y)
# 如果tanspose方法不传入参数,默认前后颠倒 a[i][j][k]-->a[k][j][i]
# transpose(0,2,1) a[i][j][k]-->a[i][k][j]
#
# display(y.transpose(0,2,1))
运行结果:
array([[1, 2],
[3, 4]])
array([[1, 3],
[2, 4]])
In [113]:
x = np.array([[1,2],[3,4]])
y = np.array([[2,3],[1,2]])
display(x,y)
# 不是矩阵乘法运算
# display(x*y)
# 使用dot实现矩阵乘法(点积)运算,如果dot传的参数是一个具体的数值,则对该数组对象做广播的操作,即每个 元素都乘传递的具体数值
# display(x.dot(y))
display(x.dot(3))
运行结果:
array([[1, 2],
[3, 4]])
array([[2, 3],
[1, 2]])
array([[ 3, 6],
[ 9, 12]])
In [120]:
# sort 排序
x = np.array([3,-1,2])
# display(np.sort(x))
y=np.array([[3,2],[1,2]])
display(y)
# sort对数组内容进行排序,默认按照最后一个轴的方向排序,如果是二维,按照水平方向排序,从小到大
# display(np.sort(y,axis=1))
# argsort 对数组内容对应的下标进行排序,
display(np.argsort(y))
运行结果:
array([[3, 2],
[1, 2]])
array([[1, 0],
[0, 1]], dtype=int64)
17、归一化矩阵
将矩阵值转化为0到1区间
- 归一化公式:x-min/max-min max为每列最大值,min为每列最小值
90 1
80 2
70 2
min 70 1
max 90 2
90-70/90-70=20/20=1
80-70/90-70=10/20=0.5
In [5]:
x = np.array([[90,1],[80,2],[70,2]])
# 得到0方向最大值
max = x.max(0)
# 得到0方向最小值
min = x.min(0)
# 得到max-min的范围值
range = max-min
# 矩阵减去min在0方向的复制,除以范围在0方向上复制
shape = x.shape
y = x - np.tile(min,(shape[0],1))
y = y/np.tile(range,(shape[0],1))
y
Out[5]:
array([[ 1. , 0. ],
[ 0.5, 1. ],
[ 0. , 1. ]])
In [4]:
a = np.tile([1,2],(1,2))
a
Out[4]:
array([[1, 2, 1, 2]])