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

Python numpy change 0 to -1 without changing False to -1

我有一个 numpy 数组,其值从布尔值到小数和实数不等。我从数据库中获取此数据,这意味着当一个字段丢失时 returns a 0。我想将所有零更改为 -1,将所有 False 更改为 0,将所有 False 更改为 1。然而似乎 Python无法区分False和0,所以都改成1。这是我试过的:

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

结果全为0,所有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,所有假值都为 0,所有真值都为 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

如果 Numpy 数组是同质的,或者至少如果它们具有与之关联的固定类型模式,则它们是最有效的。您只能将 ragtag 值集合保存在一个 dtype=object 的 numpy 数组中,这可能是您可以使用 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)

我从你的例子中了解到这是你的起点。现在,我要做的是定义一个函数来检查数组元素的值和类型,returns -1 用于非布尔零。然后可以将此函数 mapped 到您的数组,利用 .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 在数组的复杂版本上使用此函数,这样您就可以在不知道数组维数的情况下进行操作。