我有一个numpy数组,它只有几个非零项,可以是正的,也可以是负的。E、 g.类似这样的事情:
myArray = np.array([[ 0. , 0. , 0. ],
[ 0.32, -6.79, 0. ],
[ 0. , 0. , 0. ],
[ 0. , 1.5 , 0. ],
[ 0. , 0. , -1.71]])
最后,我希望收到一个列表,其中该列表的每个条目对应于myArray的一行,并且是依赖于myArray的相应行和另一个list的条目的函数输出的累积乘积(在下面的示例中,它被称为l)。 各个术语取决于myArray条目的符号:当它为正时,我应用“funPos”;当它为负时,我应用“funNeg”,如果条目为0,则该项将为1。因此,在上面的示例数组中,它将是:
^{pr2}$我实现如下所示,它给了我想要的输出(注意:这只是一个高度简化的玩具示例;实际的矩阵要大得多,函数更复杂)。我遍历数组的每一行,如果行的和是0,我不需要做任何计算,输出就是1。如果它不等于0,我遍历这一行,检查每个值的符号并应用适当的函数。在
import numpy as np
def doCalcOnArray(Array1, myList):
output = np.ones(Array1.shape[0]) #initialize output
for indRow,row in enumerate(Array1):
if sum(row) != 0: #only then calculations are needed
tempProd = 1. #initialize the product that corresponds to the row
for indCol, valCol in enumerate(row):
if valCol > 0:
tempVal = funPos(valCol, myList[indCol])
elif valCol < 0:
tempVal = funNeg(valCol, myList[indCol])
elif valCol == 0:
tempVal = 1
tempProd = tempProd*tempVal
output[indRow] = tempProd
return output
def funPos(val1,val2):
return val1*val2
def funNeg(val1,val2):
return val1*(val2+1)
myArray = np.array([[ 0. , 0. , 0. ],
[ 0.32, -6.79, 0. ],
[ 0. , 0. , 0. ],
[ 0. , 1.5 , 0. ],
[ 0. , 0. , -1.71]])
l = [1.1, 2., 3.4]
op = doCalcOnArray(myArray,l)
print op
输出是
[ 1. -7.17024 1. 3. -7.524 ]
哪一个是理想的。
我的问题是,是否有一种更有效的方法来实现这一点,因为对于大型阵列来说,这是相当“昂贵”的。在
编辑: 我接受了Gabijit的回答,因为他提出的纯numpy解决方案似乎是我正在处理的阵列中最快的解决方案。请注意,RaJa也有一个很好的工作解决方案,需要panda和dave的解决方案很好地工作,可以作为一个很好的例子,如何使用发电机和numpy的“沿_轴应用”。在
那么,让我们看看我是否理解你的问题。在
0
映射到1
x>0
映射到funPos(x)
所以,我要这样做:
1号文件:
对于2:
^{pr2}$编辑:要将索引传递给funPos,funNeg,您可以执行以下操作:
这是我尝试过的-使用reduce,map。我不知道这有多快-但这是你想做的吗?在
编辑4:最简单、最易读的——使
l
成为一个numpy数组,然后极大地简化where
。在基本上让我们看一下最后一行,它说的是将
enumerate(xx)
中的东西累加,从1开始(最后一个参数是reduce
)。myFunc只接受myArray(row)中的元素和l
中的element@index row,并根据需要将它们相乘。在我的输出和你的不一样,所以我不确定这是否正是你想要的,但也许你可以遵循逻辑。在
我也不太确定这对大型阵列来说有多快。在
编辑:以下是一种“纯粹的裸体方式”来做到这一点。在
^{pr2}$让我尽力解释
zip(*np.where(my != 0))
部分。np.where
只返回两个numpy数组第一个数组是row的索引,第二个数组是与条件(my != 0)
匹配的列的索引。我们获取这些索引的一个元组,然后使用array.itemset
和array.item
,谢天谢地,列索引对我们是免费的,所以我们可以在列表l
中获取元素@that index。这应该比以前更快(而且可读的数量级!!)。需要timeit
来确定它是否真的存在。在编辑2:不必分别调用,因为一次调用就可以完成正反两次调用
np.where(my != 0)
。在我想这个裸体功能对你会有帮助
numpy.apply_along_axis
这里有一个实现。我还警告不要检查数组的和是否为0。由于机器精度限制,将浮点与0进行比较可能会产生意外的行为。如果你有-5和5,总和是零,我不确定这是你想要的。我使用numpy的any()函数查看是否有非零。为了简单起见,我还将您的列表(my_list)纳入全球范围。在
有可能有更快的实现,我认为沿_轴应用_实际上只是一个隐藏的循环。在
我没有测试,但我敢打赌这比你刚开始的要快,而且内存效率应该更高。在
相关问题 更多 >
编程相关推荐