Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python numpy数组中的快速值交换_Python_Arrays_Numpy - Fatal编程技术网

Python numpy数组中的快速值交换

Python numpy数组中的快速值交换,python,arrays,numpy,Python,Arrays,Numpy,这应该很简单,但对我来说似乎花费了大量的时间:我有一个只有两个值的numpy数组(例如0和255),我想用这种方式反转矩阵,所有值交换(0变成255,反之亦然)。矩阵大约有2000个大条目,所以这是一项严肃的工作!我首先尝试了numpy.invert方法,这与我的预期不完全一样。因此,我试图通过“存储”这些值并覆盖它们来实现这一点: for i in range(array.length): array[i][array[i]==255]=1 ar

这应该很简单,但对我来说似乎花费了大量的时间:我有一个只有两个值的numpy数组(例如0和255),我想用这种方式反转矩阵,所有值交换(0变成255,反之亦然)。矩阵大约有2000个大条目,所以这是一项严肃的工作!我首先尝试了numpy.invert方法,这与我的预期不完全一样。因此,我试图通过“存储”这些值并覆盖它们来实现这一点:

for i in range(array.length):
            array[i][array[i]==255]=1
            array[i][array[i]==0]=255
            array[i][array[i]==1]=0

它的行为与预期的一样,但需要很长时间(我猜是因为for循环?)。如果我将其实现为多线程计算,每个线程“反转”一个更小的子数组,会更快吗?或者还有其他更方便的方法吗?

要交换0和255,如果数据类型是整数类型之一,可以使用XOR

array ^= 255
“我首先尝试了numpy.invert方法,这与我的预期不完全一样。”

Numpy.invert正是您所需要的。你能描述一下发生了什么事吗?您是否使用无符号字节进行存储,而不是使用有符号数据类型或整数

Unsigned byte+numpy.invert应该完全满足您的要求


[您还应该看到使用无符号字节而不是更长或有符号数据类型的numpy的性能更快]

除了@JanneKarila和@EOL的优秀建议之外,值得展示一种更有效的使用掩码进行交换的方法

如果您的比较比简单地交换两个值更复杂,那么使用布尔掩码通常更有用,但您的示例以次优方式使用它

目前,您正在制作上述示例中布尔“掩码”数组的多个临时副本(例如,
数组[i]==blah
),并执行多个赋值。您可以通过只创建一次“掩码”布尔数组并反转它来避免这种情况

如果您有足够的ram用于临时复制(of
bool
dtype),请尝试以下操作:

mask = (data == 255)
data[mask] = 0
data[~mask] = 255
for i in range(len(array)):
     mask = (array[i] == 255)
     array[mask] = 0
     array[~mask] = 255
或者(等效地)可以使用
numpy。其中

data = numpy.where(data == 255, 0, 255)
如果您使用循环来避免生成完整的临时副本,并且需要保留ram,请将循环调整为类似以下内容:

mask = (data == 255)
data[mask] = 0
data[~mask] = 255
for i in range(len(array)):
     mask = (array[i] == 255)
     array[mask] = 0
     array[~mask] = 255
所有这些都已经说过,在这种情况下,减法或异或都是可行的方法,特别是如果您在适当的位置执行操作的话

您只需执行以下操作:

arr_inverted = 255-arr
这将逐个转换所有元素(255表示0,0表示255)。更一般地说,如果只有两个值a和b,“反转”只需使用
(a+b)-arr
。如果这两个值不是整数(如浮点数或复数),此也有效

正如Jaime指出的,如果内存是一个问题
subtract(255,arr,out=arr)
arr
的值交换到位

如果数组中通常有整数,Janne Karila的XOR就地解决方案的优点是比上面建议的就地差分解决方案更简洁。它可以概括为
arr^=(a^b)
,用于交换两个整数
a
b

两种方法之间的执行时间相似(通过IPython使用200×200×200的
uint8
整数数组):


如果您的数组是类型
uint8
arr\u inversed=~a
需要相同的时间来交换0和255(
~
运算符反转所有位),并且不太通用,因此不值得(使用200×200×200数组进行测试)。

这只适用于
uint8
,通常不适用于无符号整数。OP的数组可能不是
uint8
。你好,乔。谢谢你的评论,但实际上我没有说“一般无符号整数”,我说的是无符号字节,即uint8。如果他只存储0和255,那么OP可能正在使用uint8。不过,将它们打包成1/0更有意义。@那个家伙欢迎来到!你是对的,但@Joe只是想澄清一下,因为OP(或我自己,例如)可能不清楚你的确切意思。在回答中尽量明确,例如说“如果您使用的是无符号字节(
uint8
),则反转应该有效,因此可能您使用的是有符号数据类型或整数。”顺便说一句,要通知Joe,您必须在他的名字前面加@,如@Joe。这仅在数组包含整数时有效,这从问题上看并不明显。不过,没有否决票。:)事实上,最简单的想法就是最有效的想法!谢谢!旁注:我建议不要使用
array
作为数组的名称:NumPy用户希望
array
的意思是
NumPy.array
。此外,当您在numpy导入*(或pylab导入*)的
之后将代码粘贴到shell中时,您的变量会阴影numpy的
数组
。我在这里使用数组只是为了清除输入类型;)如果内存是一个问题,
np.subtract(255,arr,out=arr)
将就地执行您的方法。这两种方法都避免了OP使用
==1
掩码进行第三次复制。