我正在编写一个函数,它接受一个NumPy数组并进行规范化。我写了以下内容:
def normalize_min_max(A, axis = None):
ptr = axis
minimum = np.amin(A, ptr)
maximum = np.amax(A, ptr)
for x in np.nditer(A):
x = (x - minimum)/(maximum - minimum)
return A
不幸的是它不起作用,因为返回的数组没有改变。我该如何修理?
答案 0 :(得分:2)
在任何Python迭代中,
for x in np.nditer(A):
x = (x - minimum)/(maximum - minimum)
为迭代变量赋值会更改其引用,并且不会修改原始列表/数组。
我试过
for x in np.nditer(A):
x[:] = (x - minimum)/(maximum - minimum)
但收到错误
ValueError: assignment destination is read-only
我必须转到nditer
文档,https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.nditer.html#arrays-nditer以了解如何将其更改为读/写变量
In [388]: def normalize_min_max(A, axis = None):
...: ptr = axis
...: minimum = np.amin(A, ptr)
...: maximum = np.amax(A, ptr)
...: for x in np.nditer(A, op_flags=['readwrite']):
...: x[...] = (x - minimum)/(maximum - minimum)
...: return A
...:
...:
In [389]: normalize_min_max(np.arange(10))
Out[389]: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
糟糕,原始数组是整数
In [390]: normalize_min_max(np.arange(10.))
Out[390]:
array([ 0. , 0.11111111, 0.22222222, 0.33333333, 0.44444444,
0.55555556, 0.66666667, 0.77777778, 0.88888889, 1. ])
但我不需要迭代来执行这种计算:
In [391]: def normalize_min_max1(A, axis = None):
...: ptr = axis
...: minimum = np.amin(A, ptr, keepdims=True)
...: maximum = np.amax(A, ptr, keepdims=True)
...: return (A-minimum)/(maximum-minimum)
In [392]: normalize_min_max1(np.arange(10.))
Out[392]:
array([ 0. , 0.11111111, 0.22222222, 0.33333333, 0.44444444,
0.55555556, 0.66666667, 0.77777778, 0.88888889, 1. ])
nditer
在此上下文中有效,因为迭代变量是可修改的,因为它不是for x in A: ...
。但是,它是一个复杂的迭代器,并没有提供任何速度优势。如nditer
教程页面所示,它在nditer
中使用cython
作为踏脚石非常有用。
您的nditer
代码也不适用于轴值。我的keep_dims
参数有效:
In [396]: normalize_min_max1(np.arange(10.).reshape(5,2),0)
Out[396]:
array([[ 0. , 0. ],
[ 0.25, 0.25],
[ 0.5 , 0.5 ],
[ 0.75, 0.75],
[ 1. , 1. ]])
In [397]: normalize_min_max1(np.arange(10.).reshape(5,2),1)
Out[397]:
array([[ 0., 1.],
[ 0., 1.],
[ 0., 1.],
[ 0., 1.],
[ 0., 1.]])
In [398]: normalize_min_max1(np.arange(10.).reshape(5,2),None)
Out[398]:
array([[ 0. , 0.11111111],
[ 0.22222222, 0.33333333],
[ 0.44444444, 0.55555556],
[ 0.66666667, 0.77777778],
[ 0.88888889, 1. ]])
具有轴值的nditer
代码:
In [395]: normalize_min_max(np.arange(10.).reshape(5,2),0)
...
ValueError: could not broadcast input array from shape (2) into shape ()
nditer
变量是一个0d数组,允许对其进行修改。但这使得它与最小/最大值(可能是数组)一起使用变得复杂。我们必须在nditer
设置中包含这些数组。所以它是可能的,但通常不值得额外的工作。
答案 1 :(得分:1)
xx=function(arg){
var=quo(arg)
#print(var)
df1=df %>%
select(trust09, !!!quos(arg)) %>%
group_by(trust09) %>%
filter_(.dots=paste0(arg,'==','4|',arg,'== 5'))%>%
summarise(length(!!var))
return(df1)
}
xx('q16a')
<quosure: frame>
~arg
# A tibble: 2 x 2
trust09 `length(arg)`
<chr> <int>
1 5A3 1
2 TAN 1
或者,对于就地数组规范化,请参阅this answer。
答案 2 :(得分:1)
为什么for
循环?这是一个矢量化解决方案,其中有一些轴技巧,以确保形状与输入轴对齐:
def normalize_min_max(A, axis=None):
A = np.asarray(A)
A_min = A.min(axis=axis)
A = (np.rollaxis(A, (0 if axis is None else axis)) - A_min) / (A.max(axis=axis) - A_min)
return np.rollaxis(A, (0 if axis is None else axis))
一些结果:
In[175]: a = np.arange(4*3, dtype='float32').reshape(4, 3)
In[176]: a
Out[176]:
array([[ 0., 1., 2.],
[ 3., 4., 5.],
[ 6., 7., 8.],
[ 9., 10., 11.]], dtype=float32)
In[177]: normalize_min_max(a, None)
Out[177]:
array([[ 0. , 0.09090909, 0.18181819],
[ 0.27272728, 0.36363637, 0.45454547],
[ 0.54545456, 0.63636363, 0.72727275],
[ 0.81818181, 0.90909094, 1. ]], dtype=float32)
In[178]: normalize_min_max(a, 0)
Out[178]:
array([[ 0. , 0. , 0. ],
[ 0.33333334, 0.33333334, 0.33333334],
[ 0.66666669, 0.66666669, 0.66666669],
[ 1. , 1. , 1. ]], dtype=float32)
In[179]: normalize_min_max(a, 1)
Out[179]:
array([[ 0. , 0.5, 1. ],
[ 0. , 0.5, 1. ],
[ 0. , 0.5, 1. ],
[ 0. , 0.5, 1. ]], dtype=float32)
答案 3 :(得分:1)
一种方法:就地修改而不创建新的Numpy数组
import numpy as np
def normalize_min_max(A, axis = None):
ptr = axis
minimum = np.amin(A, ptr)
maximum = np.amax(A, ptr)
A = (A - minimum)/(maximum - minimum)
return A
np_array = np.array([[1,2, 3,4],[2,3,4,5]]) # example input
print(normalize_min_max(np_array))
输出:
[[ 0. 0.25 0.5 0.75]
[ 0.25 0.5 0.75 1. ]]
**第二种方法(你的风格):创建新的Numpy数组,其形状与输入数组相同,并将规范化的值存储在那里**
import numpy as np
def normalize_min_max(A, axis = None):
ptr = axis
norm_A = np.empty(A.shape)
minimum = np.amin(A, ptr)
maximum = np.amax(A, ptr)
delta = maximum - minimum
for indx, x in np.ndenumerate(A):
norm_A[indx] = (x - minimum)/delta
return norm_A
np_array = np.array([[1,2, 3,4], [2,3,4,5]])
print(normalize_min_max(np_array))
输出:
[[ 0. 0.25 0.5 0.75]
[ 0.25 0.5 0.75 1. ]]
注意:我假设你只对Numpy数组的所有元素的最小值/最大值感兴趣,这就是你的默认轴为None的原因。如@hpaulj为nditer所解释的那样,轴的其他值不会使用除非以外的轴的ndenumerate。如果你想使用其他轴,我建议使用上面的方法1。