Question

What I would like to plot is to make vector from high values to low values. If code would start from:

a = [[1, 8, 9, 10],[2, 15, 3, -1],[3,1,6,11],[13,15,5,-2]]
X,Y = np.meshgrid(np.arange(4), np.arange(4))
U = ?
V = ?

From this point, I should set U and V components of the vector. The magnitude of each point would be a[x][y]. I don't have much idea of how I can set U and V to make arrow from high to low value at each grid point.

Was it helpful?

Solution

Here's a solution (doesn't require numpy):

import itertools as it

a = [[1, 8, 9, 10],[2, 15, 3, -1],[3,1,6,11],[13,15,5,-2]]
rowSize = len(a[0])

maxVal = a[0][0]
maxIndex = 0
minVal = a[0][0]
minIndex = 0

for k, v in enumerate(it.chain(*a)):  # Loop through a flattened list of the values in the array, and locate the indices of the max and min values.
    if v > maxVal:
        maxVal = v
        maxIndex = k    
    if v < minVal:
        minVal = v
        minIndex = k

U = (minIndex % rowSize) - (maxIndex % rowSize)
V = (minIndex / rowSize) - (maxIndex / rowSize)

print U, ",", V

OUTPUT

2 , 2

Note that you haven't defined what behavior you want when there are two equal maximum values, as there are in your example. The code above uses the "first" (upper-leftmost) one as the true maximum, and ignores all others.

Explanation:

I flattened the list (which means I read the values like you would the words on a book - first the first row, then the second row, then the third row). Each value got a single index, like so:

0  1  2  3
4  5  6  7
8  9  10 11
12 13 14 15

For example, a value in the second row and the third column would get an index of 6, since it's the 7th value if you read the array like a book.

At the end, when we've found the index of the max or min value, we need to get 2D coordinates from the 1D index. So, we can use the mod operator (%) to get the x-value.

For example, 6 % 4 = 2, so X = 2 (the 3rd column)

To get the Y value, we use the integer division operator (/).

For example, 6 / 4 = 1, so Y = 1 (the second row)

The formulas for U and V are simply taking the X and Y values for the max and min and subtracting them to get the vector coordinates, like so:

U = xMin - xMax
V = yMin - yMax

If you're wondering, "why the heck didn't he just use the meshgrid solution I started with", there are two reasons: One, using a non-standard library like numpy is generally undesirable if there is an easy way to solve the problem without non-standard libraries, and two, if you ever need to deal with large arrays, generating a large meshgrid could become time/memory expensive.

Solution that picks shortest vector:

import itertools as it

a = [[1, 8, 9, 10],[2, 15, 3, -1],[3,1,6,11],[13,15,5,-2]]
rowSize = len(a[0])

values = sorted(enumerate(it.chain(*a)), key=lambda x:x[1])  # Pair each value with its 1D index, then sort the list.

minVal = values[0][1]
maxVal = values[-1][1]

maxIndices = map(lambda x:x[0], filter(lambda x:x[1]==maxVal, values))  # Get a list of all the indices that match the maximum value
minIndices = map(lambda x:x[0], filter(lambda x:x[1]==minVal, values))  # Get a list of all the indices that match the minimum value

def getVector(index1, index2, rowSize):  # A function that translates a pair of 1D index values to a "quiver vector"
    return ((index1 % rowSize) - (index2 % rowSize), (index1 / rowSize) - (index2 / rowSize))

vectors = [getVector(k2, k1, rowSize) for k1, k2 in it.product(maxIndices, minIndices)]  # produce a list of the vectors formed by all possible combinations of the 1D indices for maximum and minimum values

U, V = sorted(vectors, key=lambda x:(x[0]*x[0] + x[1]*x[1])**0.5)[0]

print U, ",", V

OUTPUT

2 , 0
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top