Python Numpy - Slicing赋值不正确



我有一个名为arm_resets的二维numpy数组,它具有正整数。第一列都是正整数<360. 对于除第一列以外的所有列,我需要将超过360的所有值替换为第一列同一行中的值。我认为这将是一件相对容易的事情,这是我所做的:

i = 300
over_360 = arm_resets[:, [i]] >= 360
print(arm_resets[:, [i]][over_360])
print(arm_resets[:, [0]][over_360])
arm_resets[:, [i]][over_360] = arm_resets[:, [0]][over_360]
print(arm_resets[:, [i]][over_360])

打印结果如下:

[3600 3609 3608 ... 3600 3611 3605]
[ 0  9  8 ...  0 11  5]
[3600 3609 3608 ... 3600 3611 3605]

由于在第一次打印中显示的所有数字(前3个和后3个)都大于360,因此它们应该被第三次打印中的第二次打印所取代。为什么这不起作用?

编辑:可复制示例:

df = pd.DataFrame({"start":[1,2,5,6],"freq":[1,5,6,9]})
periods = 6
arm_resets = df[["start"]].values
freq = df[["freq"]].values
arm_resets = np.pad(arm_resets,((0,0),(0,periods-1)))
for i in range(1,periods):
arm_resets[:,[i]] = arm_resets[:,[i-1]] + freq
#over_360 = arm_resets[:,[i]] >= periods
#arm_resets[:,[i]][over_360] = arm_resets[:,[0]][over_360]
arm_resets

给出注释掉的代码,打印结果如下:

array([[ 1,  2,  3,  4,  5,  6],
[ 2,  7, 12, 17, 22, 27],
[ 3,  9, 15, 21, 27, 33],
[ 4, 13, 22, 31, 40, 49]])

我的期望:

array([[ 1,  2,  3,  4,  5,  1],
[ 2,  2, 2, 2, 2, 2],
[ 3,  3, 3, 3, 3, 3],
[ 4, 4, 4, 4, 4, 4]])

现在,如果有帮助的话,我实际上要创建的最后一个2d数组是一个1/0数组,它指示哪些是填充的,所以在这个例子中,我想要这样:

array([[ 0,  1,  1,  1,  1,  1],
[ 0,  0, 1, 0, 0, 0],
[ 0,  0, 0, 1, 0, 0],
[ 0, 0, 0, 0, 1, 0]])
我从上面的arm_resets中使用的代码是:
fin = np.zeros((len(arm_resets),periods),dtype=int)
for i in range(len(arm_resets)):
fin[i,a[i]] = 1

arm_resets[:, [i]]是一个花哨索引,因此复制了数据的i列。因此,arm_resets[:, [i]][over_360] = ...在一个临时数组上调用__setitem__,该数组在语句执行后立即被丢弃。如果你想给蒙版赋值,直接在切片对象上调用__setitem__:

arm_resets[over_360, [i]] = ...

你也不需要把索引做成列表。通常最好使用简单的索引,特别是在执行赋值操作时,因为它们创建的是视图,而不是副本:

arm_resets[over_360, i] = ...

使用切片,即使下面的代码也可以工作,因为它在视图上调用__setitem__:

arm_resets[:, i][over_360] = ...

这个索引不能帮助您处理数据的每一行,因为i是一个列。事实上,如果您使用索引而不是布尔掩码,则可以在一步中处理整个矩阵,而不需要循环。索引有用的原因是您可以匹配第一列中正确行中的项:

rows, cols = np.nonzero(arm_resets[:, 1:] >= 360)
arm_resets[rows, cols] = arm_resets[rows, 1]

可以使用np.where()

first_col = arm_resets[:,0] # first col
first_col = first_col.reshape(first_col.size,1) #Transfor in 2d array
arm_resets = np.where(arm_resets >= 360,first_col,arm_resets)

可以详细地看到np。在这里工作,但基本上它比较arm_resets>= 360,如果为真,它把first_col值放在适当的位置(这里还有另一个细节与广播),如果为假,它把arm_resets值。

编辑:根据疯狂物理学家的建议。你可以直接使用arm_reset [:,0,None]代替创建first_col变量。

arm_resets = np.where(arm_resets >= 360,arm_resets[:,0,None],arm_resets)

最新更新