我试图更好地理解numpy掩码,并决定尝试一个简单的fizzbuzz练习(因为np数组是同质的,9993是"fizz", 9995 = "buzz", 9998 = "fizz")然而,我注意到一些我无法理解的行为,希望有人能解释一下。
在第一个例子中,我创建了我的蒙版:
In:
a = np.arange(32)
a[(a % 3 == 0) & (a % 5 == 0)] = 9998
a
Out:
array([9998, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 9998, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 9998, 31])
In:
a[a % 3 == 0] = 9993
a[a % 5 == 0] = 9995
a
Out:
array([9998, 1, 2, 9993, 4, 9995, 9993, 7, 8, 9993, 9995,
11, 9993, 13, 14, 9998, 16, 17, 9993, 19, 9995, 9993,
22, 23, 9993, 9995, 26, 9993, 28, 29, 9998, 31])
注意,9998没有像预期的那样被后续步骤覆盖(它既不能除3也不能除5)。到目前为止一切顺利。然而,后来我试着聪明一点,给我的面具起了名字:
In:
a = np.arange(32)
fizz = (a % 3 == 0)
buzz = (a % 5 == 0)
fizzbuzz = fizz & buzz
a[fizzbuzz] = 9998
a
Out:
array([9998, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 9998, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 9998, 31])
In:
a[fizz] = 9993
a[buzz] = 9995
a
Out:
array([9995, 1, 2, 9993, 4, 9995, 9993, 7, 8, 9993, 9995,
11, 9993, 13, 14, 9995, 16, 17, 9993, 19, 9995, 9993,
22, 23, 9993, 9995, 26, 9993, 28, 29, 9995, 31])
从我所能理解的来看,似乎在"fizzbuzz = fizz &buzz"第一步,我创建了一个蒙版,这样当应用到它上面时,它为我提供了一个数组的副本。这与仅仅将掩码写出来形成对比,后者似乎可以按预期工作并直接修改数组(15 &即使在应用了% 3和% 5掩码之后,30仍然是9998)。
我的问题是为什么会发生这种情况?在我看来,这两种情况的逻辑是完全相同的。把它写成"a[fizz &buzz]";而不是"a[fizzbuzz]"没有帮助。
我认为你的问题是,当你在第一步生成数组时,你得到了a = [0,1,2,3,...,31]
。你正在做的比较(第一个片段)是与数组中的值进行比较,而不是与de index进行比较。所以当你做第一次替换时你得到a=[9998,1,2,9998,4,9998,6...]
然后下一次替换你使用的是数值所以比较9998%3==0
当你在索引15时是False
9998%5==0
也是False
在第二种情况下,你使用布尔数组访问a
,然后你加入索引。在本例中,索引中的值并不重要。
如果你想让两者的行为相同,你可以在创建fizz和buzz时修改
a = np.arange(32)
fizzbuzz = (a % 3 == 0) & (a % 5 == 0)
a[fizzbuzz] = 9998
print(a)
fizz = (a % 3 == 0)
buzz = (a % 5 == 0)
a[fizz] = 9993
a[buzz] = 9995
print(a)
所以问题是,在这两种情况下,你用不同的数组创建了fizz和buzz(对不起,土豆英语)