In ProcessPoolExecutor of concurrent.futures, BrokenProcessPool occurs - python

from concurrent.futures import ProcessPoolExecutor
import numpy as np
def func(x):
return x+1
def main():
data = np.arange(100).reshape(10,-1)
with ProcessPoolExecutor() as executor:
for result in executor.map(func,data):
print(result)
if __name__ == '__main__':
main()
I expected this code to result in the following:
[ 1 2 3 4 5 6 7 8 9 10]
[11 12 13 14 15 16 17 18 19 20]
[21 22 23 24 25 26 27 28 29 30]
[31 32 33 34 35 36 37 38 39 40]
[41 42 43 44 45 46 47 48 49 50]
[51 52 53 54 55 56 57 58 59 60]
[61 62 63 64 65 66 67 68 69 70]
[71 72 73 74 75 76 77 78 79 80]
[81 82 83 84 85 86 87 88 89 90]
[91 92 93 94 95 96 97 98 99 100]
the result was:
BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending.
But, the following code works
###
for result in executor.map(np.sum,data):
print(result)
###
The result is
45
145
245
345
445
545
645
745
845
945
I thought because I created 'func' by myself.
Please tell me why the error is happening.

Related

Why is 4D realisation of Max-Pooling in numpy misleading?

I'm trying to understand an algorithm of Max-Pooling in numpy. There are many answers like this that offer to give a new 4 - dimensional shape to two - dimensional image and then call np.max on axis 1 and 3:
window = (2, 4)
arr = np.random.randint(99, size=(1,8,12))
shape = (arr.shape[1]//window[0], window[0], arr.shape[2]//window[1], window[1])
out = arr.reshape(shape).max(axis=(1, 3))
According to my visual understanding, I should operate on axis=(0, 2) so it will shrink to the size 1 and produce an output like so:
That makes a lot of sense but it's not correct:
arr = np.random.randint(99, size=(1,8,12)) =
[[[ 7 55 21 88 69 35 7 7 73 54 16 80]
[70 79 62 55 42 5 77 81 38 52 69 39]
[58 78 48 35 5 93 47 64 18 25 73 25]
[14 8 63 27 28 46 29 68 28 38 51 79]
[70 15 37 51 72 27 44 79 1 79 75 9]
[ 4 27 0 90 15 30 95 62 14 8 69 57]
[24 29 26 44 72 89 74 78 39 29 6 2]
[82 12 0 11 54 38 61 79 91 92 53 28]]]
--------------------------------------------------
arr.reshape(4, 2, 3, 4).max(axis=(0, 2)) =
[[73 93 75 88]
[91 92 95 90]]
--------------------------------------------------
arr.reshape(4, 2, 3, 4).max(axis=(1, 3)) =
[[88 81 80]
[78 93 79]
[90 95 79]
[82 89 92]]
So it doesn't ever agree with my picture in reality. What is the source of this disagreement? What are the reasons it's not working as expected?

How tf.data.experimental.group_by_window() operates in Tensorflow 2.0

I am trying to understand the tf.data.experimental.group_by_window() method in Tensorflow 2 but I have some difficulties.
For a reproducible example I use the one presented in the documentation:
components = np.arange(100).astype(np.int64)
dataset20 = tf.data.Dataset.from_tensor_slices(components)
dataset20 = dataset.apply(tf.data.experimental.group_by_window(key_func=lambda x: x%2, reduce_func=lambda _,\
els: els.batch(10), window_size=100))
i = 0
for elem in dataset20:
print('i is {0}\n'.format(i))
print('elem is {0}'.format(elem.numpy()))
i += 1
print('\n--------------------------------\n')
i is 0
elem is [0 2 4 6 8]
--------------------------------
i is 1
elem is [1 3 5 7 9]
--------------------------------
Part of the confusion may be that the output doesn't correspond to the example code. The actual output from this:
components = np.arange(100).astype(np.int64)
dataset20 = tf.data.Dataset.from_tensor_slices(components)
dataset20 = dataset20.apply(tf.data.experimental.group_by_window(key_func=lambda x: x%2, reduce_func=lambda _,els: els.batch(10), window_size=100))
for i, d in enumerate(dataset20):
print(i, d.numpy())
is
0 [ 0 2 4 6 8 10 12 14 16 18]
1 [20 22 24 26 28 30 32 34 36 38]
2 [40 42 44 46 48 50 52 54 56 58]
3 [60 62 64 66 68 70 72 74 76 78]
4 [80 82 84 86 88 90 92 94 96 98]
5 [ 1 3 5 7 9 11 13 15 17 19]
6 [21 23 25 27 29 31 33 35 37 39]
7 [41 43 45 47 49 51 53 55 57 59]
8 [61 63 65 67 69 71 73 75 77 79]
9 [81 83 85 87 89 91 93 95 97 99]
As described in the documentation here, the key func separates the data into groups with associated key values. In the example the key func separates the data [0, 99] into even and odd groups. The reduce_func then operates on the key, group pairs to produce another dataset. Note though that reduce_func only operates on groups of data no greater than window_size. In the example, the window size is greater than the two group sizes (100 vs 50 elements), so has no effect and all evens are given in batches of 10 followed by all odds. If window size is changed to a value less than 50 then it does have an effect. For example, if the window size is changed to 5 and also the batching is moved to outside the group_by_window function:
dataset20 = dataset20.apply(tf.data.experimental.group_by_window(key_func=lambda x: x%2, reduce_func=lambda _, els: els, window_size=5)).batch(10)
then the following output is produced:
0 [0 2 4 6 8 1 3 5 7 9]
1 [10 12 14 16 18 11 13 15 17 19]
2 [20 22 24 26 28 21 23 25 27 29]
3 [30 32 34 36 38 31 33 35 37 39]
4 [40 42 44 46 48 41 43 45 47 49]
5 [50 52 54 56 58 51 53 55 57 59]
6 [60 62 64 66 68 61 63 65 67 69]
7 [70 72 74 76 78 71 73 75 77 79]
8 [80 82 84 86 88 81 83 85 87 89]
9 [90 92 94 96 98 91 93 95 97 99]

Unable to return correct output from created function in JES

I am fairly new to jython and I am inquiring about creating a function that is dealing with a list. Basically what I am trying to do with the below function is create a function that will loop through the entirety of my list, then find the lowest value within that list and return the variable with the lowest number. Though, I keep getting a return of function min at 0x26 everytime I execute the main() I receive the same message but it seems as if the function min at 0x26 will count up ex: 0x27, 0x28... Not sure why this is. As my list only contains integers of minimum 0 to max 99.
Here is the sourcecode:
def min(dataset): #defining a function minimum, with input dataset(the list we are using)..
min = dataset[0]
for num in range(0, len(dataset)):
if dataset[num] < min:
min = dataset(num)
return min
minimum = min(dataset)
print(str(minimum))
Here is the code in its entirety. Though, I currently have a way to find the min/max values in the list. I am looking to move towards a function, as I want to know how to correctly use a function.
def main( ):
dataset = [0]
file = open("D:\numbs.dat", "r")
for line in file: #loop for writing over every line to a storage loc.
num = int(float(line)) #converting int to string
dataset.append(num) #appending the data to 'dataset' list
max = dataset[0] #setting an imaginary max initially
low = dataset[0] #setting an imaginary low initially
for i in range(0, len(dataset)): #for loop to scan thru entire list
if dataset[i] > max: #find highest through scan and replacing each max in var max
max = dataset[i]
if dataset[i] < low: #find lowest through scan and replacing each max in var max
low = dataset[i]
#printNow(dataset) #printing the list in its entirety
#printNow("The maximum is " +str(max)) #print each values of lowest and highest
#printNow("The lowest is " +str(low))
def min(dataset): #defining a function minimum..
min = dataset[0]
for num in range(0, len(dataset)):
if dataset[num] < min:
min = dataset(num)
return min
minimum = min(dataset)
print(str(minimum)) #test to see what output is.
As mentioned above, there is the for loop for finding max/min values. Though I tried doing the same exact thing for the function I am trying to create...
the contents of the numbs.dat can be found here (1001 entries):
70
75
76
49
73
76
52
63
11
25
19
89
17
48
5
48
29
41
23
84
28
39
67
48
97
34
0
24
47
98
0
64
24
51
45
11
37
77
5
54
53
33
91
0
27
0
80
5
11
66
45
57
48
25
72
8
38
29
93
29
58
5
72
36
94
18
92
17
43
82
44
93
10
38
31
52
44
10
50
22
39
71
46
40
33
51
51
57
27
24
40
61
88
87
40
85
91
99
6
3
56
10
85
38
61
91
31
69
39
74
9
17
80
96
49
0
47
68
12
5
6
60
81
51
62
87
70
66
50
30
30
22
45
35
2
39
23
63
35
69
83
84
69
6
54
74
3
29
31
54
45
79
21
74
30
77
77
80
26
63
84
21
58
54
69
2
50
79
90
26
45
29
97
28
57
22
59
2
72
1
92
35
38
2
47
23
52
77
87
34
84
15
84
13
23
93
19
50
99
74
59
4
73
93
29
61
8
45
10
20
15
95
58
43
75
19
61
39
68
47
69
58
88
82
33
30
72
21
74
12
18
0
52
50
62
21
66
26
56
84
16
12
7
45
58
22
26
95
82
6
74
12
16
2
61
58
22
39
0
53
88
79
71
13
54
25
31
93
48
91
90
45
23
54
42
39
78
25
95
58
2
41
61
72
98
91
48
97
93
11
12
1
35
80
81
86
38
70
67
55
55
87
73
79
31
43
97
79
3
51
17
58
70
34
59
61
28
46
13
42
18
0
18
75
75
62
50
62
85
49
83
71
63
32
27
59
42
46
8
13
39
25
13
94
17
48
73
40
31
31
86
23
81
40
92
24
94
67
30
18
74
78
62
89
1
27
95
99
33
53
74
5
84
88
8
52
0
24
21
99
1
74
84
94
29
25
83
93
98
40
21
66
93
28
72
63
77
9
71
18
87
50
77
48
68
88
22
33
16
79
68
69
94
64
5
28
33
22
21
74
44
62
68
47
93
69
9
42
44
87
64
97
42
34
90
70
91
12
18
84
65
23
99
1
55
6
1
23
92
50
96
96
68
27
17
98
42
10
27
26
20
13
94
73
75
12
12
25
33
1
33
67
61
0
98
71
35
75
68
56
45
11
1
69
57
9
15
96
69
2
0
65
44
86
78
97
17
4
81
23
4
43
24
72
70
57
21
91
84
94
40
96
40
78
46
67
6
7
16
49
24
14
12
82
73
60
42
76
62
10
84
49
75
89
43
47
31
68
15
11
32
37
98
72
40
25
69
30
64
60
48
21
11
74
54
24
60
10
96
29
39
53
48
24
68
4
52
12
6
91
15
86
77
65
68
22
91
36
72
82
81
9
77
0
5
83
27
88
17
35
66
76
78
81
19
51
87
66
26
59
65
2
37
37
73
34
98
37
78
92
17
52
62
40
50
84
34
22
25
42
90
19
86
76
68
42
9
89
57
78
64
89
12
34
94
9
77
58
32
27
97
93
79
35
32
75
97
79
65
90
53
43
98
4
99
5
79
38
99
60
78
64
90
2
39
42
52
2
21
77
15
8
87
13
0
4
7
43
76
31
74
16
87
50
73
49
14
35
10
37
91
44
88
71
95
75
98
7
17
23
13
16
77
20
50
50
74
78
58
30
21
74
76
93
5
74
94
83
23
67
18
5
50
47
56
79
26
84
78
48
71
43
41
8
91
23
7
11
96
87
12
42
32
44
99
67
99
64
96
52
19
79
60
66
52
62
17
61
54
24
25
36
4
78
3
94
91
62
65
76
94
2
52
25
61
55
49
88
85
96
5
46
56
48
17
25
3
70
62
3
50
45
47
58
12
41
27
42
90
91
71
53
4
79
47
68
43
87
35
63
10
49
4
81
45
88
80
6
92
47
70
40
7
33
70
61
30
9
55
42
83
26
72
57
77
91
13
15
33
13
62
49
43
65
73
98
59
56
77
62
12
25
33
53
78
73
1
17
44
56
95
10
33
89
33
20
56
69
66
60
53
83
58
43
33
25
21
8
28
65
51
70
53
78
49
30
64
17
76
9
2
32
87
77
39
25
21
66
65
54
81
49
15
27
7
14
4
11
94
9
84
23
13
95
45
67
57
20
3
58
50
97
35
68
47
41
84
59
46
34
19
25
77
29
41
89
80
61
70
40
1
18
32
70
86
76
25
98
99
40
43
92
43
4
70
78
72
71
85
14
84
73
92
60
23
57
44
56
6
96
39
91
63
43
39
71
80
18
93
54
1
4
46
68
93
74
74
88
52
88
55
24
19
92
53
59
1
91
48
47
Let me know what the heck I am doing wrong. Thanks!
#ohGosh welcome to stack overflow. You are almost there with the solution. There are few problems with your program
1) Nums.dat file contains just one line with numbers separated by spaces, not a new line(\n). In order to get the read the numbers from the file do the following
dataset = [] #Create an empty list
file = open("D:\numbs.dat", "r") #Open the file
for line in file:
tempData = line.split(" ") #Returns a list with space used as delimiter
dataset = map(int, tempData) #Convert string data to int
2) Wrong way to get data from a list in the min function
Use
min = dataset[num]
Instead of
min = dataset(num)
Fix this and your program will work. Cheers.

python index error pop up when I have a longer input

I am solving one sorting problem. I encountered with one problem which has been troubling me for 2 days.
I ran the code for a shorter input, it worked just as what I expected.
However, when I put a much longer input into this program, runtime error emerges.
Here is the code:
row_number, row_length = input().split()
row_number, row_length = int(row_number), int(row_length)
def row_input():
data_input = []
for i in range(0,row_number):
row = list(map(int,input().split()))
data_input.append(row)
return data_input
def sort_data(data):
k = int(input())
sorted_data = []
for row in data:
sorted_data.append(row[k])
sorted_data.sort()
n = 0
while n < row_number:
for m in data:
if sorted_data[n] == m[k]:
print_data(m)
n = n + 1
def print_data(data):
b=''
for n in data:
b= b + str(n).ljust(len(str(n))+1)
print(b)
data = row_input()
sort_data(data)
Here is the short input:
10 3
1 1 1
1 1 2
1 1 3
1 1 4
2 2 5
2 3 6
2 3 7
2 3 8
2 3 9
2 4 0
1
Here is the longer input:
100 10
64 79 18 94 46 81 74 97 71 92
46 24 23 20 68 15 53 93 24 91
17 66 34 64 28 5 55 25 44 96
16 71 80 84 5 79 63 77 69 77
33 77 24 13 58 81 41 36 73 62
93 26 16 55 61 51 39 69 29 45
44 85 1 48 23 59 52 82 50 37
77 74 9 21 35 54 81 57 32 76
82 21 72 49 98 21 77 64 6 63
68 17 93 83 12 43 84 28 96 86
9 16 3 89 38 11 70 25 41 38
49 99 31 19 85 97 80 63 16 69
50 85 80 75 36 48 56 69 63 94
78 80 83 86 92 60 56 90 22 73
69 81 45 9 67 25 82 46 68 82
98 38 23 31 38 83 37 76 69 82
95 48 21 64 25 6 38 96 69 23
44 97 46 54 21 56 65 51 66 34
87 22 27 24 55 48 90 10 8 51
21 6 74 78 8 88 26 63 72 43
64 4 42 20 54 91 2 51 79 40
93 76 52 58 40 78 98 27 53 48
85 23 86 30 91 49 81 4 59 9
88 96 77 95 36 71 7 52 14 20
69 98 21 94 14 35 28 97 3 9
60 47 56 34 35 61 9 44 80 92
4 76 57 28 60 3 46 4 6 17
59 44 88 7 71 60 84 12 91 38
76 57 5 2 25 12 46 62 32 68
14 15 11 1 34 20 54 58 45 38
89 49 16 43 74 51 80 22 88 31
8 98 51 73 32 13 59 12 56 92
36 82 9 63 77 79 77 25 52 91
63 82 58 75 13 20 79 89 55 89
58 37 93 1 29 72 78 95 47 35
90 82 58 60 55 86 82 22 44 94
55 17 51 99 29 92 1 79 96 34
32 78 41 1 24 52 11 80 3 25
30 32 32 71 85 80 63 23 80 97
35 22 11 71 10 48 43 58 31 33
30 98 60 58 28 71 95 28 21 29
74 4 13 99 90 64 28 27 73 4
52 21 52 31 35 82 35 64 21 71
92 85 13 48 5 32 92 70 15 85
47 55 25 80 24 22 19 78 17 43
3 91 71 53 49 39 96 88 59 61
79 26 98 2 95 95 70 38 82 85
69 67 41 11 95 39 20 19 96 36
11 74 48 23 84 49 47 43 27 90
4 28 35 14 70 62 52 94 46 91
72 11 14 82 59 51 93 98 55 79
90 84 84 24 21 81 11 57 27 78
98 97 59 51 89 40 96 35 25 59
73 85 64 17 46 9 79 54 27 15
48 91 7 56 41 6 4 26 96 39
43 22 34 89 52 59 55 52 38 42
10 31 9 8 21 46 29 4 97 4
44 49 78 31 53 29 11 35 46 14
44 39 57 35 9 63 85 5 97 24
9 72 49 50 41 47 23 71 15 45
51 6 98 64 75 35 39 48 2 50
92 22 72 60 96 15 17 4 79 27
90 30 98 28 92 8 83 71 24 62
5 54 86 14 71 96 87 2 58 78
37 61 60 30 46 96 49 58 27 48
14 59 22 35 75 60 55 28 91 85
21 1 85 85 78 67 24 69 22 17
76 61 84 64 33 76 61 10 33 95
71 9 1 32 31 80 69 7 25 59
69 64 78 85 21 88 56 70 92 74
79 12 8 9 54 56 37 44 1 84
6 66 54 5 82 17 41 25 3 71
8 44 63 17 75 43 87 15 85 3
15 42 15 59 38 22 46 27 19 13
54 71 76 93 67 39 46 12 78 46
23 82 71 34 31 61 94 58 10 62
30 8 43 38 7 23 77 38 93 32
32 72 46 59 64 45 14 73 62 72
76 26 47 89 25 73 79 28 60 48
41 58 85 55 29 64 39 84 20 87
24 8 70 16 69 32 17 26 58 16
40 53 40 63 22 37 11 74 7 8
23 4 56 39 27 94 91 72 14 61
41 86 3 29 41 15 99 50 82 84
33 5 22 93 73 86 99 87 26 66
73 25 55 46 69 38 99 14 43 55
43 21 82 30 90 66 6 67 49 25
81 38 65 40 80 7 90 82 33 13
18 45 1 90 53 51 51 96 32 90
32 69 51 22 71 85 80 61 99 23
88 8 41 92 4 25 64 89 30 75
93 85 99 87 67 3 54 16 98 57
33 54 31 83 64 93 3 24 65 81
74 19 15 66 17 14 34 50 57 16
10 30 20 97 32 85 83 89 68 18
46 82 9 14 54 50 55 28 26 96
29 96 3 33 12 52 11 26 19 22
50 81 95 59 76 53 10 9 72 87
25 85 54 43 53 13 52 70 38 76
20 14 30 80 23 43 27 67 42 11
5
Here is the error while running the longer input:
Traceback (most recent call last):
File "solution.py", line 30, in <module>
sort_data(data)
File "solution.py", line 19, in sort_data
if sorted_data[n] == m[k]:
IndexError: list index out of range
The problem is in your sorting logics, because it is highly possible you increment n by more than one in one iteration of the while loop if there are multiple matching rows in the dataset.
The right solution is simpler than you think:
def sort_data(data):
k = int(input())
output = sorted(data, key=lambda row: row[k])
for r in output:
print_data(r)
UPDATE: The smallest dataset on what your algorithm fails is:
2 1
2
1
0
A small modification on your function will stop it from overindexing. The key is to store sorted_data[n] in a variable, and that way it will not try to over index sorted_data when no more output is expected.
def sort_data(data):
k = int(input())
sorted_data = []
for row in data:
sorted_data.append(row[k])
sorted_data.sort()
n = 0
while n < row_number:
key = sorted_data[n]
for m in data:
if key == m[k]:
print_data(m)
n = n + 1
UPDATE:
The sorted function's key parameter is a function, which just selects a value what to sort by. In your case, selects the kth column, which is what you want to sort by.

Fill in missing values with nearest neighbour in Python numpy masked arrays?

I am working with a 2D Numpy masked_array in Python.
I need to change the data values in the masked area such that they equal the nearest unmasked value.
NB. If there are more than one nearest unmasked values then it can take any of those nearest values (which ever one turns out to be easiest to codeā€¦)
e.g.
import numpy
import numpy.ma as ma
a = numpy.arange(100).reshape(10,10)
fill_value=-99
a[2:4,3:8] = fill_value
a[8,8] = fill_value
a = ma.masked_array(a,a==fill_value)
>>> a [[0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 -- -- -- -- -- 28 29]
[30 31 32 -- -- -- -- -- 38 39]
[40 41 42 43 44 45 46 47 48 49]
[50 51 52 53 54 55 56 57 58 59]
[60 61 62 63 64 65 66 67 68 69]
[70 71 72 73 74 75 76 77 78 79]
[80 81 82 83 84 85 86 87 -- 89]
[90 91 92 93 94 95 96 97 98 99]],
I need it to look like this:
>>> a.data
[[0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 ? 14 15 16 ? 28 29]
[30 31 32 ? 44 45 46 ? 38 39]
[40 41 42 43 44 45 46 47 48 49]
[50 51 52 53 54 55 56 57 58 59]
[60 61 62 63 64 65 66 67 68 69]
[70 71 72 73 74 75 76 77 78 79]
[80 81 82 83 84 85 86 87 ? 89]
[90 91 92 93 94 95 96 97 98 99]],
NB. where "?" could take any of the adjacent unmasked values.
What is the most efficient way to do this?
Thanks for your help.
I generally use a distance transform, as wisely suggested by Juh_ in this question.
This does not directly apply to masked arrays, but I do not think it will be that hard to transpose there, and it is quite efficient, I've had no problem applying it to large 100MPix images.
Copying the relevant method there for reference :
import numpy as np
from scipy import ndimage as nd
def fill(data, invalid=None):
"""
Replace the value of invalid 'data' cells (indicated by 'invalid')
by the value of the nearest valid data cell
Input:
data: numpy array of any dimension
invalid: a binary array of same shape as 'data'. True cells set where data
value should be replaced.
If None (default), use: invalid = np.isnan(data)
Output:
Return a filled array.
"""
#import numpy as np
#import scipy.ndimage as nd
if invalid is None: invalid = np.isnan(data)
ind = nd.distance_transform_edt(invalid, return_distances=False, return_indices=True)
return data[tuple(ind)]
You could use np.roll to make shifted copies of a, then use boolean logic on the masks to identify the spots to be filled in:
import numpy as np
import numpy.ma as ma
a = np.arange(100).reshape(10,10)
fill_value=-99
a[2:4,3:8] = fill_value
a[8,8] = fill_value
a = ma.masked_array(a,a==fill_value)
print(a)
# [[0 1 2 3 4 5 6 7 8 9]
# [10 11 12 13 14 15 16 17 18 19]
# [20 21 22 -- -- -- -- -- 28 29]
# [30 31 32 -- -- -- -- -- 38 39]
# [40 41 42 43 44 45 46 47 48 49]
# [50 51 52 53 54 55 56 57 58 59]
# [60 61 62 63 64 65 66 67 68 69]
# [70 71 72 73 74 75 76 77 78 79]
# [80 81 82 83 84 85 86 87 -- 89]
# [90 91 92 93 94 95 96 97 98 99]]
for shift in (-1,1):
for axis in (0,1):
a_shifted=np.roll(a,shift=shift,axis=axis)
idx=~a_shifted.mask * a.mask
a[idx]=a_shifted[idx]
print(a)
# [[0 1 2 3 4 5 6 7 8 9]
# [10 11 12 13 14 15 16 17 18 19]
# [20 21 22 13 14 15 16 28 28 29]
# [30 31 32 43 44 45 46 47 38 39]
# [40 41 42 43 44 45 46 47 48 49]
# [50 51 52 53 54 55 56 57 58 59]
# [60 61 62 63 64 65 66 67 68 69]
# [70 71 72 73 74 75 76 77 78 79]
# [80 81 82 83 84 85 86 87 98 89]
# [90 91 92 93 94 95 96 97 98 99]]
If you'd like to use a larger set of nearest neighbors, you could perhaps do something like this:
neighbors=((0,1),(0,-1),(1,0),(-1,0),(1,1),(-1,1),(1,-1),(-1,-1),
(0,2),(0,-2),(2,0),(-2,0))
Note that the order of the elements in neighbors is important. You probably want to fill in missing values with the nearest neighbor, not just any neighbor. There's probably a smarter way to generate the neighbors sequence, but I'm not seeing it at the moment.
a_copy=a.copy()
for hor_shift,vert_shift in neighbors:
if not np.any(a.mask): break
a_shifted=np.roll(a_copy,shift=hor_shift,axis=1)
a_shifted=np.roll(a_shifted,shift=vert_shift,axis=0)
idx=~a_shifted.mask*a.mask
a[idx]=a_shifted[idx]
Note that np.roll happily rolls the lower edge to the top, so a missing value at the top may be filled in by a value from the very bottom. If this is a problem, I'd have to think more about how to fix it. The obvious but not very clever solution would be to use if statements and feed the edges a different sequence of admissible neighbors...
For more complicated cases you could use scipy.spatial:
from scipy.spatial import KDTree
x,y=np.mgrid[0:a.shape[0],0:a.shape[1]]
xygood = np.array((x[~a.mask],y[~a.mask])).T
xybad = np.array((x[a.mask],y[a.mask])).T
a[a.mask] = a[~a.mask][KDTree(xygood).query(xybad)[1]]
print a
[[0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 13 14 15 16 17 28 29]
[30 31 32 32 44 45 46 38 38 39]
[40 41 42 43 44 45 46 47 48 49]
[50 51 52 53 54 55 56 57 58 59]
[60 61 62 63 64 65 66 67 68 69]
[70 71 72 73 74 75 76 77 78 79]
[80 81 82 83 84 85 86 87 78 89]
[90 91 92 93 94 95 96 97 98 99]]

Categories