I want to calculate some values for each side of a grid of points

87 Views Asked by At

I have a numpy array of n x m values, which may look something like this:

[[ 1, 2, 1, 3, 5],
[ 0, 4, 2, 4, 1],
[ 1, 1, 1, 0, 2]]

I want to calculate the difference and mean from every grid point to its neighbours. I am not sure on how to do this in an easy and fast way, since the actual arrays are much bigger. I also dont know, which is the best way to represent the resulting data. I was thinking something like an nm x nm array, where each value represents a tuple of the desired calculations like this (Pn :


     P1                      P2                          P3                           ...
P1 (0, P1)                   ((P1 - P2), mean(P1, P2))  ((P1 - P2), mean(P1, P2)) 
P2 ((P2 - P1), mean(P2, P1)) (0, P2)                    ((P2 - P3), mean(P2, P3))
P3 ((P3 - P1), mean(P3, P1)) ((P3 - P2), mean(P3, P2))  (0, P3)
...

but this seems rather wasteful, since I am only interested in the calcuations for the 8 neighbours.

I think two n x m output grids like this would be best for further processing:

[[(mean1, mean2, mean3...), (mean1, mean2, mean3...), ...],
[(mean1, mean2, mean3...), (mean1, mean2, mean3...), ...],
[(mean1, mean2, mean3...), (mean1, mean2, mean3...), ...]]

This resulting grid should hold a tuple of 8 values for every cell position, but this is also not optimal. This feels like a problem, which should have very clever solutions, so I am hoping for you to understand what I want to do and maybe help me achieve this goal :)

I tried a lot of slicing in numpy and I am expecting an output array (however this may look) which holds all the calculated data.

1

There are 1 best solutions below

0
Tanishq Chaudhary On

I am assuming that you want to find the tuple (difference, mean) for each neighbor of a cell, for all the cells.

Option 1:

If you are okay with some wasted space, you can use a list of 8 tuples of (difference, mean), where all the cells on the edges will have some None values.

from itertools import product

def get_neighs(r, c):
    """
    Returns a 8 tupled information array for each cell at (r, c).
    """
    source = grid[r][c]
    data = []
    for dr , dc in product([-1, 0, 1], repeat=2):
        # if same as source cell, skip
        if dr == dc == 0: 
            continue
        
        # if in bounds, can find difference and mean
        if 0 <= r + dr < m and 0 <= c + dc < n:
            nr, nc = r + dr, c + dc
            current = grid[nr][nc]
            data.append((current - source, (current + source) / 2))
        # otherwise append dummy values to maintain ordering
        else:
            data.append((None, None))

    return data

grid = [
    [1,2,3],
    [4,5,6],
    [7,8,9]
]

m, n = len(grid), len(grid[0])

for r in range(m):
    for c in range(n):
        print(get_neighs(r,c))

Option 2:

Have a dict for each cell, to save on space. The key of the dict tells which location the neighbor is, according to the current.

def get_efficient_neighs(r, c):
    """
    Returns a dict of information tuple for each cell at (r, c).
    """
    source = grid[r][c]
    data = {}
    for dr , dc in product([-1, 0, 1], repeat=2):
        # if same as source cell, skip
        if dr == dc == 0: 
            continue
        # if not in bounds, skip
        if not (0 <= r + dr < m and 0 <= c + dc < n):
            continue
        
        nr, nc = r + dr, c + dc
        current = grid[nr][nc]
        data[f"{dr},{dc}"] = ((current - source, (current + source) / 2))

    return data