set the elements not included by np.where as np.nan
Question:
How can I set all the elements that are not 7 as np.nan?
import numpy as np
data = np.array([[0,1,2,3,4,7,6,7,8,9,10],
[3,3,3,4,7,7,7,8,11,12,11],
[3,3,3,5,7,7,7,9,11,11,11],
[3,4,3,6,7,7,7,10,11,11,11],
[4,5,6,7,7,9,10,11,11,11,11]])
result = np.where(data==7)
data[~result] = np.nan
print data
Traceback (most recent call last):
File "M:test.py", line 10, in <module>
data[~result] = np.nan
TypeError: bad operand type for unary ~: 'tuple'
Answers:
There must be a better way but this is the best I can think of right now. Make another array of all np.nan
, and then replace the values at the indices in result
with the real values:
data_nan = np.full(data.shape, np.nan)
data_nan[result] = data[result]
data = data_nan
If you want to get a list of all indices that are not in result
, you could do this, though I think the above is probably better:
inc = np.core.rec.fromarrays(result)
all_ind = np.core.rec.fromarrays(np.indices(data.shape).reshape(2,-1))
exc = np.setdiff1d(all_ind, inc)
data[exc['f0'], exc['f1']] = np.nan
This works by turning each pair of indices into one element of a structured array, so that they can be compared as set elements to a similar array of all indices. Then we do the set difference of these and get the rest.
Use the 3-argument form of np.where:
In [49]: np.where(data==7, data, np.nan)
Out[49]:
array([[ nan, nan, nan, nan, nan, 7., nan, 7., nan, nan, nan],
[ nan, nan, nan, nan, 7., 7., 7., nan, nan, nan, nan],
[ nan, nan, nan, nan, 7., 7., 7., nan, nan, nan, nan],
[ nan, nan, nan, nan, 7., 7., 7., nan, nan, nan, nan],
[ nan, nan, nan, 7., 7., nan, nan, nan, nan, nan, nan]])
or
In [62]: np.choose(data==7, [np.nan, data])
Out[62]:
array([[ nan, nan, nan, nan, nan, 7., nan, 7., nan, nan, nan],
[ nan, nan, nan, nan, 7., 7., 7., nan, nan, nan, nan],
[ nan, nan, nan, nan, 7., 7., 7., nan, nan, nan, nan],
[ nan, nan, nan, nan, 7., 7., 7., nan, nan, nan, nan],
[ nan, nan, nan, 7., 7., nan, nan, nan, nan, nan, nan]])
Regarding the requirement that the integer indices returned by using_filters be used in this solution, I think there is a better alternative. If you were to remove the np.where
from using_filters
:
def using_filters(data):
return np.logical_and.reduce(
[data == f(data, footprint=np.ones((3,3)), mode='constant', cval=np.inf)
for f in (filters.maximum_filter, filters.minimum_filter)])
then using_filters
would return a boolean mask. Using a boolean mask would make this problem even easier:
import numpy as np
import scipy.ndimage.filters as filters
def using_filters(data):
return np.logical_and.reduce(
[data == f(data, footprint=np.ones((3,3)), mode='constant', cval=np.inf)
for f in (filters.maximum_filter, filters.minimum_filter)])
data = np.array([[0,1,2,3,4,7,6,7,8,9,10],
[3,3,3,4,7,7,7,8,11,12,11],
[3,3,3,5,7,7,7,9,11,11,11],
[3,4,3,6,7,7,7,10,11,11,11],
[4,5,6,7,7,9,10,11,11,11,11]], dtype='float')
result = using_filters(data)
data[~result] = np.nan
print data
# [[ nan nan nan nan nan nan nan nan nan nan nan]
# [ nan nan nan nan nan nan nan nan nan nan nan]
# [ nan nan nan nan nan 7. nan nan nan nan nan]
# [ nan nan nan nan nan nan nan nan nan 11. nan]
# [ nan nan nan nan nan nan nan nan nan nan nan]]
You can get the values you want from data
, and fill data
with nan
and then copy the values back to data
:
import numpy as np
data = np.array([[0,1,2,3,4,7,6,7,8,9,10],
[3,3,3,4,7,7,7,8,11,12,11],
[3,3,3,5,7,7,7,9,11,11,11],
[3,4,3,6,7,7,7,10,11,11,11],
[4,5,6,7,7,9,10,11,11,11,11]], float)
result = np.where(data==7)
values = data[result]
data.fill(np.nan)
data[result] = values
How can I set all the elements that are not 7 as np.nan?
import numpy as np
data = np.array([[0,1,2,3,4,7,6,7,8,9,10],
[3,3,3,4,7,7,7,8,11,12,11],
[3,3,3,5,7,7,7,9,11,11,11],
[3,4,3,6,7,7,7,10,11,11,11],
[4,5,6,7,7,9,10,11,11,11,11]])
result = np.where(data==7)
data[~result] = np.nan
print data
Traceback (most recent call last):
File "M:test.py", line 10, in <module>
data[~result] = np.nan
TypeError: bad operand type for unary ~: 'tuple'
There must be a better way but this is the best I can think of right now. Make another array of all np.nan
, and then replace the values at the indices in result
with the real values:
data_nan = np.full(data.shape, np.nan)
data_nan[result] = data[result]
data = data_nan
If you want to get a list of all indices that are not in result
, you could do this, though I think the above is probably better:
inc = np.core.rec.fromarrays(result)
all_ind = np.core.rec.fromarrays(np.indices(data.shape).reshape(2,-1))
exc = np.setdiff1d(all_ind, inc)
data[exc['f0'], exc['f1']] = np.nan
This works by turning each pair of indices into one element of a structured array, so that they can be compared as set elements to a similar array of all indices. Then we do the set difference of these and get the rest.
Use the 3-argument form of np.where:
In [49]: np.where(data==7, data, np.nan)
Out[49]:
array([[ nan, nan, nan, nan, nan, 7., nan, 7., nan, nan, nan],
[ nan, nan, nan, nan, 7., 7., 7., nan, nan, nan, nan],
[ nan, nan, nan, nan, 7., 7., 7., nan, nan, nan, nan],
[ nan, nan, nan, nan, 7., 7., 7., nan, nan, nan, nan],
[ nan, nan, nan, 7., 7., nan, nan, nan, nan, nan, nan]])
or
In [62]: np.choose(data==7, [np.nan, data])
Out[62]:
array([[ nan, nan, nan, nan, nan, 7., nan, 7., nan, nan, nan],
[ nan, nan, nan, nan, 7., 7., 7., nan, nan, nan, nan],
[ nan, nan, nan, nan, 7., 7., 7., nan, nan, nan, nan],
[ nan, nan, nan, nan, 7., 7., 7., nan, nan, nan, nan],
[ nan, nan, nan, 7., 7., nan, nan, nan, nan, nan, nan]])
Regarding the requirement that the integer indices returned by using_filters be used in this solution, I think there is a better alternative. If you were to remove the np.where
from using_filters
:
def using_filters(data):
return np.logical_and.reduce(
[data == f(data, footprint=np.ones((3,3)), mode='constant', cval=np.inf)
for f in (filters.maximum_filter, filters.minimum_filter)])
then using_filters
would return a boolean mask. Using a boolean mask would make this problem even easier:
import numpy as np
import scipy.ndimage.filters as filters
def using_filters(data):
return np.logical_and.reduce(
[data == f(data, footprint=np.ones((3,3)), mode='constant', cval=np.inf)
for f in (filters.maximum_filter, filters.minimum_filter)])
data = np.array([[0,1,2,3,4,7,6,7,8,9,10],
[3,3,3,4,7,7,7,8,11,12,11],
[3,3,3,5,7,7,7,9,11,11,11],
[3,4,3,6,7,7,7,10,11,11,11],
[4,5,6,7,7,9,10,11,11,11,11]], dtype='float')
result = using_filters(data)
data[~result] = np.nan
print data
# [[ nan nan nan nan nan nan nan nan nan nan nan]
# [ nan nan nan nan nan nan nan nan nan nan nan]
# [ nan nan nan nan nan 7. nan nan nan nan nan]
# [ nan nan nan nan nan nan nan nan nan 11. nan]
# [ nan nan nan nan nan nan nan nan nan nan nan]]
You can get the values you want from data
, and fill data
with nan
and then copy the values back to data
:
import numpy as np
data = np.array([[0,1,2,3,4,7,6,7,8,9,10],
[3,3,3,4,7,7,7,8,11,12,11],
[3,3,3,5,7,7,7,9,11,11,11],
[3,4,3,6,7,7,7,10,11,11,11],
[4,5,6,7,7,9,10,11,11,11,11]], float)
result = np.where(data==7)
values = data[result]
data.fill(np.nan)
data[result] = values