incorrect output using numpy.where to set wind directions

Question:

I have some pretty simple Python code where I’m trying to label wind directions as "N", "NE", etc based on the actual direction in degrees. I am getting some really strange results, and don’t know why.

dir = np.array([307,45,198,355])

Sixteen_UD = np.empty(len(dir),dtype='str')
Sixteen_UD[np.where(np.logical_or(dir >= 348.75, dir < 11.25))] = "N"
Sixteen_UD[np.where(np.logical_and(dir >= 11.25, dir < 33.75))] = 'NNE'
Sixteen_UD[np.where(np.logical_and(dir >= 33.75, dir < 56.25))] = 'NE'
Sixteen_UD[np.where(np.logical_and(dir >= 56.25, dir < 78.75))] = 'ENE'
Sixteen_UD[np.where(np.logical_and(dir >= 78.75, dir < 101.25))] = 'E'
Sixteen_UD[np.where(np.logical_and(dir >= 101.25, dir < 123.75))] = 'ESE'
Sixteen_UD[np.where(np.logical_and(dir >= 123.75, dir < 146.25))] = 'SE'
Sixteen_UD[np.where(np.logical_and(dir >= 146.25, dir < 168.75))] = 'SSE'
Sixteen_UD[np.where(np.logical_and(dir >= 168.75, dir < 191.25))] = 'S'
Sixteen_UD[np.where(np.logical_and(dir >= 191.25, dir < 213.75))] = 'SSW'
Sixteen_UD[np.where(np.logical_and(dir >= 213.75, dir < 236.25))] = 'SW'
Sixteen_UD[np.where(np.logical_and(dir >= 236.25, dir < 258.75))] = 'WSW'
Sixteen_UD[np.where(np.logical_and(dir >= 258.75, dir < 281.25))] = 'W'
Sixteen_UD[np.where(np.logical_and(dir >= 281.25, dir < 303.75))] = 'WNW'
Sixteen_UD[np.where(np.logical_and(dir >= 303.75, dir < 326.25))] = "NW"
Sixteen_UD[np.where(np.logical_and(dir >= 326.25, dir < 348.75))] = 'NNW'

This is the output I’m getting:

array(['N', 'N', 'S', 'N'], dtype='<U1')

It should be:

['NW','NE','SSW','N']

What is wrong with what I’m doing?

Asked By: user8229029

||

Answers:

Your array stores single characters:

>>> Sixteen_UD.dtype
dtype('<U1')

U is the np.str_ unicode string type, length 1. The output is entirely correct, it’s the first letter of the correct directions.

To store arbitrary-length strings, use object as the dtype:

Sixteen_UD = np.empty(len(dir), dtype=object)

That’ll store any Python object.

You could also state you want to store strings of length 3, explicitly specify a length with the U[length] notation. Use np.zeros() to fill this array with empty strings:

Sixteen_UD = np.zeros(len(dir), dtype='U3')

as np.empty() can lead to somewhat random looking initial data if the array is created in an area of memory with non-zero data present.

With dtype='U3', the output of your code then becomes:

array(['NW', 'NE', 'SSW', 'N'], dtype='<U3')
Answered By: Martijn Pieters
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.