2016-11-13 52 views
2

给定一个数组,我想它正常化使得每行总和为1归一numpy的阵列

目前,我有以下代码:

import numpy 
w = numpy.array([[0, 1, 0, 1, 0, 0], 
       [1, 0, 0, 0, 0, 1], 
       [0, 0, 0, 0, 0, 1], 
       [1, 0, 0, 0, 1, 0], 
       [0, 0, 0, 1, 0, 1], 
       [0, 1, 1, 0, 1, 0]], dtype = float) 


def rownormalize(array): 
    i = 0 
    for row in array: 
     array[i,:] = array[i,:]/sum(row) 
     i += 1 

我有两个问题:

1)代码有效,但我想知道是否有更优雅的方式。

2)如何将数据类型转换为浮点数,如果它是int?我试过

if array.dtype == int: 
    array.dtype = float 

但它不起作用。

回答

6

你可以做1)这样的:

array /= array.sum(axis=1, keepdims=True) 

和2)这样的:

array = array.astype(float) 
+0

如果我添加“如果array.dtype == int:array.astype(float)”到我的函数的开始,它给了我一个零矩阵(除了一个元素是1) – wwl

+0

您需要重新分配,请参阅编辑。 – Julien

+0

如果我添加'return array'并将我的代码更改为'w = rownormalize(w)'而不是'rownormalize(w)',那么该方法可行。有没有办法可以做到这一点,而无需做出上述改变?如果你不确定,那么它很好 – wwl

4

部门即使broadcasted所有元素可能是昂贵的。重点对性能的替代,将预先计算行求和的倒数,并使用这些执行broadcasted乘法代替,像这样 -

w *= 1.0/w.sum(1,keepdims=1) 

运行测试 -

In [588]: w = np.random.rand(3000,3000) 

In [589]: out1 = w/w.sum(axis=1, keepdims=True) #@Julien Bernu's soln 

In [590]: out2 = w*(1.0/w.sum(1,keepdims=1)) 

In [591]: np.allclose(out1,out2) 
Out[591]: True 

In [592]: %timeit w/w.sum(axis=1, keepdims=True) #@Julien Bernu's soln 
10 loops, best of 3: 66.7 ms per loop 

In [593]: %timeit w*(1.0/w.sum(1,keepdims=1)) 
10 loops, best of 3: 40 ms per loop 
+1

差异不是很大,但因为它很容易完成,所以我会尽量记住这个技巧! – Julien

+0

@JulienBernu对!特别是用'broadcast',这个派上用场! – Divakar