In [119]: np.array([1,0,2,0],dtype=bool)                                             
Out[119]: array([ True, False,  True, False])

In [120]: np.array([1, False, 2, False, []])                                         
Out[120]: array([1, False, 2, False, list([])], dtype=object)

Note the dtype. With object dtype, the elements of the array are Python objects, just like they are in the source list.

In the first case the array dtype is boolean. The elements represent boolean values, but they are not, themselves, Python True/False objects. Strictly speaking Out[119] does not contain np.bool_ objects. Out[119][1] is type bool_, but that's the result of the 'unboxing'. It's what ndarray indexing produces when you ask for an element. (This 'unboxing' distinction is true for all non-object dtypes.)

Normally we don't create dtype objects, preferring np.array(True), but to follow your example:

In [124]: np.bool_(True)                                                             
Out[124]: True
In [125]: type(np.bool_(True))                                                       
Out[125]: numpy.bool_
In [126]: np.bool_(True) is True                                                     
Out[126]: False
In [127]: type(True)                                                                 
Out[127]: bool

is is a strict test, not just for equality, but identity. Objects of different classes don't satisfy a is test. Objects can satisfy the == test without satisfying the is test.

Let's play with the object dtype array:

In [129]: np.array([1, False, 2, np.bool_(False), []])                               
Out[129]: array([1, False, 2, False, list([])], dtype=object)
In [130]: [i is False for i in _]                                                    
Out[130]: [False, True, False, False, False]

In the Out[129] display, the two False objects display the same, but the Out[130] test shows they are different.


To focus on your questions.

  • np.bool_(False) is a unique object, but distinct from False. As you note it has many of the same attributes/methods as np.array(False).

  • If the array dtype is bool it does not contain Python bool objects. It doesn't even contain np.bool_ objects. However indexing such an array will produce a bool_. And applying item() to that in turn produces a Python bool.

  • If the array object dtype, it most likely will contain Python bool, unless you've taken special steps to include bool_ objects.

Answer from hpaulj on Stack Overflow
🌐
NumPy
numpy.org › doc › stable › user › basics.types.html
Data types — NumPy v2.4 Manual
Note that, above, we could have used the Python float object as a dtype instead of numpy.float64. NumPy knows that int refers to numpy.int_, bool means numpy.bool, that float is numpy.float64 and complex is numpy.complex128.
Top answer
1 of 5
13
In [119]: np.array([1,0,2,0],dtype=bool)                                             
Out[119]: array([ True, False,  True, False])

In [120]: np.array([1, False, 2, False, []])                                         
Out[120]: array([1, False, 2, False, list([])], dtype=object)

Note the dtype. With object dtype, the elements of the array are Python objects, just like they are in the source list.

In the first case the array dtype is boolean. The elements represent boolean values, but they are not, themselves, Python True/False objects. Strictly speaking Out[119] does not contain np.bool_ objects. Out[119][1] is type bool_, but that's the result of the 'unboxing'. It's what ndarray indexing produces when you ask for an element. (This 'unboxing' distinction is true for all non-object dtypes.)

Normally we don't create dtype objects, preferring np.array(True), but to follow your example:

In [124]: np.bool_(True)                                                             
Out[124]: True
In [125]: type(np.bool_(True))                                                       
Out[125]: numpy.bool_
In [126]: np.bool_(True) is True                                                     
Out[126]: False
In [127]: type(True)                                                                 
Out[127]: bool

is is a strict test, not just for equality, but identity. Objects of different classes don't satisfy a is test. Objects can satisfy the == test without satisfying the is test.

Let's play with the object dtype array:

In [129]: np.array([1, False, 2, np.bool_(False), []])                               
Out[129]: array([1, False, 2, False, list([])], dtype=object)
In [130]: [i is False for i in _]                                                    
Out[130]: [False, True, False, False, False]

In the Out[129] display, the two False objects display the same, but the Out[130] test shows they are different.


To focus on your questions.

  • np.bool_(False) is a unique object, but distinct from False. As you note it has many of the same attributes/methods as np.array(False).

  • If the array dtype is bool it does not contain Python bool objects. It doesn't even contain np.bool_ objects. However indexing such an array will produce a bool_. And applying item() to that in turn produces a Python bool.

  • If the array object dtype, it most likely will contain Python bool, unless you've taken special steps to include bool_ objects.

2 of 5
3

There is some confusion with the variables, what is happening is a "confusion" between the module and python, use isinstance(variable, type) to check what is it an if is usable on your code.

Creating a single variable as a bool variable works just fine, python reeds it correctly:

np_bool = np.bool(True)
py_bool = True

print(isinstance(np_bool, bool)) # True
print(isinstance(py_bool, bool)) # True

But with lists it can be different, numpy bool lists are not bool values on a list as you can see in this example:

# Regular list of int
arr0 = [-2, -1, 0, 1, 2]

# Python list of bool
arr1 = [True, False, True, False]

# Numpy list of bool, from int / bool
arr3_a = np.array([-2, -1, 0, 1, 2], dtype=bool)
arr3_b = np.array([True, False, True, False], dtype=bool)

print(isinstance(arr0[0], int))    # True
print(isinstance(arr1[0], bool))   # True

print(isinstance(arr3_a[0], bool)) # False
print(isinstance(arr3_b[0], bool)) # False

In order to use a variable from the numpy list is required a conversion with bool()

arr3_a = np.array([-2, -1, 0, 1, 2], dtype=bool)

x = (bool(arr3_a[0]) is True)
print(isinstance(x, bool)) # True

Quick example of use:

arr3_a = np.array([-2, -1, 0, 1, 2], dtype=bool)

for c in range(0, len(arr3_a)):
    if ( bool(arr3_a[c]) == True ):
        print(("List value {} is True").format(c))
    else:
        print(("List value {} is False").format(c))
🌐
Joergdietrich
joergdietrich.github.io › python-numpy-bool-types.html
Python and numpy Bool Types
In numpy we can make things even a little more convoluted if we mix Python bools and numpy.bool_ in an object array. In [7]: b = np.array([True, True, False, np.True_], dtype=object) print(b.astype(np.bool)) print((~b).astype(np.bool)) [ True True False True] [ True True True False] My advise above to use logical not also does not work for numpy arrays because not is not applied element-wise but tries to evaluate the boolean value of the entire array.
🌐
NumPy
numpy.org › devdocs › user › basics.types.html
Data types — NumPy v2.5.dev0 Manual
Note that, above, we could have used the Python float object as a dtype instead of numpy.float64. NumPy knows that int refers to numpy.int_, bool means numpy.bool, that float is numpy.float64 and complex is numpy.complex128.
🌐
GitHub
github.com › spyder-ide › spyder › issues › 18054
`'numpy.dtype[bool_]' object is not callable` when debugging code that uses Pandas · Issue #18054 · spyder-ide/spyder
May 29, 2022 - # works fine in debug and run import pandas as pd import numpy as np from nelson_siegel_svensson.calibrate import calibrate_ns_ols t = np.array([0.0, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0]) y = np.array([0.01, 0.011, 0.013, 0.016, 0.019, 0.021, 0.026, 0.03, 0.035, 0.037, 0.038, 0.04]) curve, status = calibrate_ns_ols(t, y, tau0=1.0) # starting value of 1.0 for the optimization of tau assert status.success print(curve) Universe=pd.read_csv('GlobalCreditUniverse.csv',sep=";",header=2)
Published   May 29, 2022
Author   DDAAVVEE888
🌐
GitHub
github.com › numba › numba › issues › 5080
dtype=np.bool doesn't work in array constructors · Issue #5080 · numba/numba
January 14, 2020 - import numpy as np from numba import jitclass # import the decorator from numba import int32, float32, bool_ # import the types spec = [ ('value', int32), # a simple scalar field ('array', bool_[:]), # an array field ] @jitclass(spec) class Bag(object): def __init__(self, value): self.value = value self.array = np.zeros(value, dtype=np.bool) @property def size(self): return self.array.size def increment(self, val): for i in range(self.size): self.array[i] = val return self.array if __name__ == '__main__': p = Bag(100) p.increment(1) print(p.size)
Author   rjzak
🌐
NumPy
numpy.org › doc › stable › reference › arrays.dtypes.html
Data type objects (dtype) — NumPy v2.4 Manual
A data type object (an instance of numpy.dtype class) describes how the bytes in the fixed-size block of memory corresponding to an array item should be interpreted.
🌐
Rip Tutorial
riptutorial.com › creating a boolean array
numpy Tutorial => Creating a boolean array
A boolean array can be created manually by using dtype=bool when creating the array. Values other than 0, None, False or empty strings are considered True. import numpy as np bool_arr = np.array([1, 0.5, 0, None, 'a', '', True, False], dtype=bool) ...
Find elsewhere
Top answer
1 of 2
12

Yes, you can write a one bit raster with rasterio*.

You need to:

  1. write to a format that supports a 1bit dataset, such as GeoTIFF;
  2. ensure your numpy array is np.uint8/ubyte so rasterio doesnt raise the TypeError: invalid dtype: 'bool' exception; and
  3. pass the NBITS=1 creation option to tell the underlying GDAL GeoTIFF driver to create a one bit file.
import numpy as np
import rasterio as rio

with rio.open('test_byte.tif') as src:
    data = src.read()
    profile = src.profile

with rio.open('test_bit.tif', 'w', nbits=1, **profile) as dst:
    dst.write(data)
    # If your array is not a byte dtype, you need to cast it as ubyte/uint8
    # dst.write(data.astype(np.uint8))

Checking output file size

$ ls -sh test_bit.tif
228K test_bit.tif

$ ls -sh test_byte.tif
1.8M test_byte.tif

$ gdalinfo test_bit.tif
Driver: GTiff/GeoTIFF
Files: test_bit.tif
Size is 1588, 1167
<snip...>
Band 1 Block=1588x41 Type=Byte, ColorInterp=Palette
  Image Structure Metadata:
    NBITS=1

$ gdalinfo test_byte.tif
Driver: GTiff/GeoTIFF
Files: test_byte.tif
Size is 1588, 1167
<snip...>
Band 1 Block=1588x5 Type=Byte, ColorInterp=Gray

2 of 2
9

If you call rasterio.dtypes.check_dtype(np.bool_) you'll see that it's not a known dtype, because gdal doesn't support a true 1-bit dtype. GDT_Byte is the smallest. The list that rasterio is checking against is:

dtype_fwd = {
0: None,            # GDT_Unknown
1: ubyte,           # GDT_Byte
2: uint16,          # GDT_UInt16
3: int16,           # GDT_Int16
4: uint32,          # GDT_UInt32
5: int32,           # GDT_Int32
6: float32,         # GDT_Float32
7: float64,         # GDT_Float64
8: complex_,        # GDT_CInt16
9: complex_,        # GDT_CInt32
10: complex64,      # GDT_CFloat32
11: complex128}    # GDT_CFloat64

uint8 and int8 are mapped to the ubyte, as seen here:

https://github.com/mapbox/rasterio/blob/master/rasterio/dtypes.py#L29-L45

🌐
W3Schools
w3schools.com › python › numpy › numpy_data_types.asp
NumPy Data Types
import numpy as np arr = np.array([1.1, 2.1, 3.1]) newarr = arr.astype(int) print(newarr) print(newarr.dtype) Try it Yourself » ... import numpy as np arr = np.array([1, 0, 3]) newarr = arr.astype(bool) print(newarr) print(newarr.dtype) Try it Yourself »
🌐
NumPy
numpy.org › doc › stable › › reference › generated › numpy.dtype.html
numpy.dtype — NumPy v2.4 Manual
Boolean indicating whether the dtype is a struct which maintains field alignment.
🌐
GeeksforGeeks
geeksforgeeks.org › python-boolean-array-in-numpy
Boolean Array in NumPy - Python - GeeksforGeeks
April 29, 2025 - Explanation: dtype=bool argument convert the array a into Boolean values. It treats non-zero values as True and zeros as False. np.where() function in NumPy is a versatile tool for conditional operations.
🌐
NumPy
numpy.org › doc › 2.1 › user › basics.types.html
Data types — NumPy v2.1 Manual
Note that, above, we could have used the Python float object as a dtype instead of numpy.float64. NumPy knows that int refers to numpy.int_, bool means numpy.bool, that float is numpy.float64 and complex is numpy.complex128.
🌐
GitHub
github.com › pandas-dev › pandas › issues › 39817
API: common dtype for bool + numeric: upcast to object or coerce to numeric? · Issue #39817 · pandas-dev/pandas
February 15, 2021 - >>> pd.concat([pd.DataFrame({'a': np.array([], dtype=bool)}), pd.DataFrame({'a': np.array([], dtype=float)})]).dtypes a object dtype: object >>> pd.concat([pd.DataFrame({'a': np.array([True], dtype=bool)}), pd.DataFrame({'a': np.array([1.0], dtype=float)})]).dtypes a object dtype: object
Author   jorisvandenbossche
🌐
Noveltech
noveltech.dev › booleans-python-numpy
Booleans in Python: Beware of Numpy | Noveltech
August 24, 2021 - So what was this issue? Well, turns out that the numpy package uses a custom type for boolean variables, which is bool_. This makes sense since numpy implements ctype arrays so comparisons are done in cython and not python so they needed to ...
🌐
NumPy
numpy.org › doc › 2.1 › reference › generated › numpy.dtype.html
numpy.dtype — NumPy v2.1 Manual
Boolean indicating whether the dtype is a struct which maintains field alignment.
🌐
GitHub
github.com › numba › numba › issues › 1311
`np.bool` vs `np.bool_` · Issue #1311 · numba/numba
July 10, 2015 - This might be deliberate (numba docs do only say np.bool_ is supported), but I'm getting an error when I use np.bool instead of np.bool_ (what exactly is the difference?) I'm using Miniconda w/ Python 3.4: In [1]: import numba In [2]: import numpy as np In [3]: numba.__version__ Out[3]: '0.20.0' In [4]: @numba.jit(nopython=True) ...: def f(): ...: np.zeros(5, dtype=np.bool) # works fine if I use np.bool_ ...: In [5]: f() --------------------------------------------------------------------------- TypingError Traceback (most recent call last) <ipython-input-4-0ec059b9bfe1> in <module>() ----> 1
Author   alanhdu
🌐
NumPy
numpy.org › devdocs › reference › generated › numpy.dtype.html
numpy.dtype — NumPy v2.5.dev0 Manual
Boolean indicating whether the dtype is a struct which maintains field alignment.