Python numpy将0更改为-1而不将False更改为-1

时间:2016-11-07 09:47:30

标签: python numpy mask

我有一个numpy数组,其值从布尔到十进制和实数不等。我从数据库中获取这些数据,这意味着当一个字段丢失时它会返回0.我想将所有零值更改为-1,所有Falses更改为0并将Trues更改为1.但是,似乎Python无法使区分False和0,从而将两者都改为1.这就是我所尝试过的:

X[X==0] = -1
X[X==False] = 0
X[X==True] =1

结果全部为零,所有Falses都变为-1。我该如何解决这个问题?

编辑: 这是我的数组样本:

[[0.03829744 0.0 True False True True 6.0]
[0.0 0.0 True False True True 6.0]
[0.09174341 0.0 True False True True 6.0]
[0.03489284 2 0 True True False 0 6.0]]

我希望所有0.0值都为-1,所有False值为0,所有True值为1。

编辑2:循环遍历所有值,但必须有更优雅的解决方案

for i in xrange(X.shape[0]):
    for j in xrange(X.shape[1]):
        if X[i,j] == 0.0 and type(X[i, j]) == float:
            X[i][j] = -1

1 个答案:

答案 0 :(得分:3)

如果Numpy数组是同构的,或者至少如果它们具有与之关联的固定类型模式,则它们是最有效的。你只能在dtype=object的numpy数组中保存你的ragtag值集合,这可能是你用numpy做的最有效的事情。

相应地,没有高效(本地numpy)方法(我知道)可以让你访问每个元素的类型。当使用numpy时,这通常不会出现。

因此,我能想到使代码更优雅的唯一方法是将双循环转换为函数调用。我将使用map,它可能仍然没有原生numpy函数那么快(因为后者将在C中编译),但它可能比python双循环更快,更清晰同样。

然而,我在评论中也注意到了一个注意事项:您的示例数据不是矩形的,即它无法转换为2d numpy数组,无论您如何努力。我假设您在组合MCVE时犯了一个错误,并从示例数据的第四行省略了一个元素(从而使您的数组(4,7)成形)。

import numpy as np

# dummy data as nested list, make sure it's rectangular
datlist = [[0.03829744, 0.0, True, False, True, True, 6.0],
           [0.0, 0.0, True, False, True, True, 6.0],
           [0.09174341, 0.0, True, False, True, True, 6.0],
           [0.03489284, 0, True, True, False, 0, 6.0]]  #dropped an element here

# create a numpy array of dtype object from datlist
dat = np.array(datlist,dtype=object)

我从你的例子中得知,这是你的出发点。现在,我要做的是定义一个函数来检查数组元素的值和类型,并为非bool零返回-1。然后,此函数可以map到您的数组,利用.ravel()访问整个数据范围:

def zeroswap(elem):
    # replace non-bool zeros with -1, leave the rest alone
    return -1 if elem==0 and elem is not False else elem

dat.ravel()[:] = list(map(zeroswap,dat.ravel())) #list() needed for python3

结果数组如下所示:

array([[0.03829744, -1, True, False, True, True, 6.0],
       [-1, -1, True, False, True, True, 6.0],
       [0.09174341, -1, True, False, True, True, 6.0],
       [0.03489284, -1, True, True, False, -1, 6.0]], dtype=object)

如您所见,浮点数和整数零都已转换为-1。这对我来说是有意义的,这是因为我们只检查了非False零。如果要区分这两种数字零,可以在zeroswap函数中轻松完成。如果要切换bool值,也可以这样做。这是一个升级后的功能,可以转换0.0 -> -10 -> -1False -> 0True -> 1other -> other

def zeroswap(elem):
    if type(elem) is bool:
        return int(elem)
    elif elem==0:
        return -1
    else:
        return elem

您可以将此函数调用到各种元素,以确保它能够执行您期望的操作。最重要的是,你应该map这个功能优于阵列的分散版本,让你无需了解阵列的维度即可操作。