这里主要记录numpy遇到的一些问题,目录有点凌乱,日后再做整理
问题描述
寻找numpy中非的0元素
问题解决
方法有三种,如下
# 1,返回的是两个adarray,代表了位置索引
a = np.array()
row, col = [i for i in np.nonzero(a)]
nonzero = []
for i, j in zip(row, col):
nonzero.append(a[i, j]) # 位置索引
# 2,直接返回非0的值
a[a!=0]
# 3
where = np.where(a==0)
row, col = [i for i in where]
之后和1一样
问题描述
想压缩数据的维度,有维度是多余的,如何将他们去掉
问题解决
运用numpy的np.squeeze
函数
a = np.random.random((1,4))
print(a)
b = np.squeeze(a, axis=0)
print(b)
print(b.shape)
# out
[[0.87072838 0.55459801 0.20885144 0.72031326]]
[0.87072838 0.55459801 0.20885144 0.72031326]
(4,)
需要注意的是:
np.squeeze
只能够压缩本来是1维的数据,如果压缩不是1维度的维度则会产生报错np, squeeze
相反的操作是np.expand_dims
,能够扩张维度。这在pytorch中,相同功能的操作是torch.unsqueeze
问题描述
当我们说重复数据的时候,一般会有两种方式
repea
t方法,第二种操作可以写循环用np.concatenate
进行实现a = np.array([[1,3,4],[4,5,6]])
a
# out
[[1 3 4]
[4 5 6]]
第一种操作的实现,以整体为单位,重复复制n次
# 复制某一行
n = 5
for index in range(n):
concat = np.concatenate([concat, a], axis=0) if index!= 0 else a
print(concat)
# out, a has been concat n times
[[1, 3, 4],
[4, 5, 6],
[1, 3, 4],
[4, 5, 6],
[1, 3, 4],
[4, 5, 6],
[1, 3, 4],
[4, 5, 6],
[1, 3, 4],
[4, 5, 6]]
第二种操作的实现,以某一行或者某一列为单位进行复制,调用repeat函数,调用有两种方式
np.repeat()
NumPy.ndarray
对象调用对象方法实现object.repreat()
a = np.array([[1,3,4],[4,5,6]])
np.repeat(a, 2, axis=0)
# 输出
array([[1, 3, 4],
[1, 3, 4],
[4, 5, 6],
[4, 5, 6]])
# 通过对象方法调用
a.repeat(4, axis=0)
# 输出
array([[1, 3, 4],
[1, 3, 4],
[4, 5, 6],
[4, 5, 6]])
注意: np.repeat
方法是对每一行,或者每一列进行调用的,而pytorch则不同,其是以数据整体为一个单位调用的,这种方式会灵活许多,因为其可以通过repeat + reshape
的方法实现对行、列元素重复n次的操作
问题描述
想将数组铺开,进行操作
思路
通过np.ravel
方法能够将数组铺开为一维数组并对其进行修改
a = np.arange(12).reshape(4,3)
a.ravel()
# out
[1,2,3,4,5,6,7,8,9,10,11,12]
问题描述
最近偶尔会在别人论文的一些代码中看见ndarray, torch.tensor
变换形状的一些骚操作,可以大大提高代码的效率,由于自己基础非常弱,打算把reshape
的机制完全搞清楚
问题解决
首先,需要说明np.reshape
方法的机制,其处理顺序如下:
ndarray
铺平成维度为1的array
(有不同的铺开方式,可以是沿着行铺开,也可以是沿着列铺开)ndarray
做切割操作,也就是说,如果reshape中order的参数为‘C’
的话,则用该array的长度除以新size
的行数,可以得到切割点的index
,然后以切割点将铺平的ndarray
切割为n个ndarray
,再依次以axis=0
的方式将这些切割出来的ndarray
进行拼接,则可以得到reshape后的矩阵三维数组
的话,方式也是完全一样的,只不过3个维度需要2次切割,2维数组只需要1次切割,具体可以看下面的代码a = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
print(a.shape)
print(a)
b = a.ravel(order='c') # return a flatterned ndarray, data not changed
print('\n', b.shape)
print(b)
# transform into shape (3, 2, 2)
c = a.reshape((3,2,2))
print(c.shape)
print(c)
# output
# a
(2, 2, 3)
[[[ 1 2 3]
[ 4 5 6]]
[[ 7 8 9]
[10 11 12]]]
# b
(12,)
[ 1 2 3 4 5 6 7 8 9 10 11 12]
#c
(3, 2, 2)
[[[ 1 2]
[ 3 4]]
[[ 5 6]
[ 7 8]]
[[ 9 10]
[11 12]]]
注意:在reshape
函数中,有一个参数为order
,其实这个参数就是指铺开待重塑数组时的方式而已,如果为c
的话,就是默认按照行进行铺开。如果为F
的话,就是默认按照列进行铺开,并且铺开之后得到切割点切割后的ndarray
是按照axis=1
也就是沿着列的方式进行拼接的,由于我们一般都是对行进行操作,这里就不继续写代码了,理解即可。
想继续了解order="F"
的操作可以看这篇文章这篇文章
问题描述
如何删除NumPy.ndarray
中的某个元素,或者某个行
思路
在二维的ndarray
中,是不能删除某个元素的,因为ndarray
是结构化数据,删除了某个元素这个结构就没有办法表现出来(列入中间删除了某个数据,那么这个维度依然是二维)。因此在二维的ndarray中只能够删除某一行、或者某一列。在一维的ndarray
中,因为删除增加元素是可以更改维度的,因此可以删除某一个元素。
元素的删除用np.delete
方法来实现,需要设置两个参数,一个是删除元素的位置索引,可以传入list, ndarray
,一个是axis
参数,代表想要删除的是行还是列,在一维数组中不需要设置,因为只有一个维度
# ndarray with 1 dim
a = np.array([1,2,3,4,5,6,7,8])
print(a)
np.delete(a, [0,1,2],)
# out
array([1, 2, 3, 4, 5, 6, 7, 8]) # a
array([4, 5, 6, 7, 8]). # elements deleted according to index
# ndarray with 2 dims
a = np.array([[1,3,4],[4,5,6],[1,1,1]])
print(a)
np.delete(a, [0,1], axis=0) # delete row 0 and 1
# out
array([[1, 3, 4],
[4, 5, 6],
[1, 1, 1]])
array([[1, 1, 1]]) # only row 2 left
注意:想要获得的某个索引的具体位置,可以用np.where
函数来获得,并将得到的loc
参数传入想要删除的ndarray
中就可以了
问题描述
️,这是一个比较有用的函数
问题解决
该函数可以用来定位元素,也可以用来赋值。
np.where
来定位元素的时候,其功能和np.asarray(object).nonzero()
其返回和数组尾数相同的tuple
,其中含有由索引构成的ndarray
。注意:如object.nonzero()
中的object已经是根据逻辑运算判断过后的矩阵,那么nonzero()
就是返回这个矩阵中为True
的那些位置np.where
来赋值的时候,其遵循的代码是np.where(condition, x, y)
,当condition中的元素值为True时,取x的值,为False
时,取y的值。注意:要么condition, x, y
三者的维度相同,要么x, y
为标量,否则会报错np.where
对DataFrame
对象也有用代码如下:
a = np.random.randint(0,4, (3,3))
threshold = 1
np.where(a>0)
# output
(array([0, 0, 1, 1, 2, 2]), array([0, 2, 0, 1, 0, 2]))
可以看到,返回的是一个tuple
,其长度和输入数据的维度数量是相同的。如果输入数组是二维数组,那么tuple
中的第一个 array
返回的就是满足条件的行索引,第二个array
返回的是满足条件的列索引
问题描述
取切片索引
问题解决
np.s_[start_index:end_index:step]
没啥特别的,生成的就是一个array。如果要省略某一个参数,直接不填值即可
注意:这里的np.s_其实就是类似于slice函数
a = np.array([1,2,3,4,5,6,7])
s = np.s_[0::2] # start from zero, end as the last, step by 2
print(s)
print(a[s])
# output
slice(0, None, 2)
[1 3 5 7]
描述
slice
函数返回的就是一个slice对象
,他能够接受三个参数,start, stop, step
,其中step是可选的参数
注:如果slice
函数中含有None
,他代表的是"slice nothing",也就是不切片任何操作,所以就等同于:
(全取)
a = [0,1,2,3]
s_ = slice(0, None, 2)
a[s_]
a[0::2]
>>> output
[0, 2]
[0, 2]
问题描述
在实际中为了维度匹配,经常需要更改ndarray
的维度,比较复杂的扩张以及压缩维度已经有np.expand_dims
以及np.squeeze
来解决,这里介绍两种非常简单的日常方法
问题解决
a = np.arange(12)
a = a.reshape(-1, 1) # 通过reshape函数
np.newaxis
a = np.arange(12)
a[np.newaxis, :] # 0维度新添加数据,其余维度切片全部数据
None
方法a = np.arange(12)
a[None, :]
问题描述
想要知道numpy的逐行操作
问题解决
因为numpy是储存的全部为数值,所以如果要对每个元素进行操作,直接用numpy的操作就可以了。但是如果每一行一列的操作是不一样的,这个时候就要用到apply_along_axis
操作。
func1d
是函数,接受匿名函数lambda x
,axis
是对哪一行/列进行操作,arr
是要操作的ndarray
a = np.arange(8).reshape(2,4)
print(a)
norm = lambda x: x/x.sum()
b = np.apply_along_axis(func1d=norm, axis=1, arr=a)
print(b)
# output
[[0 1 2 3]
[4 5 6 7]]
[[0. 0.16666667 0.33333333 0.5 ]
[0.18181818 0.22727273 0.27272727 0.31818182]]
完美解决
问题描述
在进行股票数据处理的时候,经常需要生成移动窗口的数据,但是每次都自己写循环写的方法其实很笨,因此去stackoverflow上面看了一下,发现大家的方法都好灵活好厉害,在此记录两个方法在这里插入代码片
问题解决
slice
,并循环利用hstack
方法:a = np.array([[00,01], [10,11], [20,21], [30,31], [40,41], [50,51]])
w = np.hstack((a[:-2],a[1:-1],a[2:]))
w
>>> output
array([[ 0, 1, 10, 11, 20, 21],
[10, 11, 20, 21, 30, 31],
[20, 21, 30, 31, 40, 41],
[30, 31, 40, 41, 50, 51]])
其方法的巧妙住处在于,处理后数据的每一行与上一行的差距都是固定的,因此其直接通过在axis=0的维上直接去切片,然后进行拼接操作,写成函数就是
def window_stack(a, stepsize=1, width=3):
n = a.shape[0]
return np.hstack( a[i:1+n+i-width:stepsize] for i in range(0,width) )
注意:此方法同样适用于维度为2以上的情况
>>> a = np.array([[00,01], [10,11], [20,21], [30,31], [40,41], [50,51]])
>>> a
array([[ 0, 1],
[10, 11],
[20, 21], #define our 2d numpy array
[30, 31],
[40, 41],
[50, 51]])
>>> a = a.flatten()
>>> a
array([ 0, 1, 10, 11, 20, 21, 30, 31, 40, 41, 50, 51]) #flattened numpy array
>>> indexer = np.arange(6)[None, :] + 2*np.arange(4)[:, None]
>>> indexer
array([[ 0, 1, 2, 3, 4, 5],
[ 2, 3, 4, 5, 6, 7], #sliding window indices
[ 4, 5, 6, 7, 8, 9],
[ 6, 7, 8, 9, 10, 11]])
>>> a[indexer]
array([[ 0, 1, 10, 11, 20, 21],
[10, 11, 20, 21, 30, 31], #values of a over sliding window
[20, 21, 30, 31, 40, 41],
[30, 31, 40, 41, 50, 51]])
>>> np.sum(a[indexer], axis=1)
array([ 63, 123, 183, 243]) #sum of values in 'a' under the sliding window.
下一次再进行解释