Home > Enterprise >  Why is this numpy array still a generator?
Why is this numpy array still a generator?

Time:08-16

This code is supposed to generate a vector field from data (data) which describes how often a cell is visited.

def vectorfield(maze, walk, data):
    # associate a zero vector with each location in walkable space
    tempdata = {pair:np.zeros(2) for pair in walk}

    for x, y in tempdata.keys():
        value = data[x][y] # how many times an agent visited this cell
        for dx, dy in itertools.product([-1, 0, 1], [-1, 0, 1]):
            # if (x dx, y dy) is a neigbhor of (x, y) use its value for computation
            if dx or dy and (x dx, y dy) in walk:
                tempdata[(x, y)]  = np.array([dx*value,dy*value])

    # largest length of corresponding vectors
    m = np.amax(np.sqrt(vx**2   vy**2) for vx, vy in tempdata.values())
    t = {key : value/m for key, value in tempdata.items()}
    tempdata = t

    x, y = tempdata.keys()
    u, v = tempdata.values()

    return x, y, u, v

The bit of code with {key : value/m for key, value in tempdata.items()} yields an error: TypeError: unsupported operand type(s) for /: 'float' and 'generator'. The division comes from the fact that I need to normalize each vector. Why is that error displayed?

CodePudding user response:

(np.sqrt(vx**2   vy**2) for vx, vy in tempdata.values())

creates a generator expression. np.amax doesn't change the type, it just returns the max value. Try to make it a list instead

m = np.amax([np.sqrt(vx**2   vy**2) for vx, vy in tempdata.values()])

CodePudding user response:

Native Python max, and many other functions, take an iterable as their parameter, meaning an object that has either a __getitem__ method or an __iter__ method which returns an iterator (source). This includes lists, tuples and generators.

numpy functions take a different approach, usually accepting an "array-like" parameter. Generally, these have __getitem__ and also have a defined length. Generators do not have a defined length. If it gets something else, such as a generator, it treats it as a 0-dimensional array containing only that object. The maximum of such an array is simply the generator object it contains.

As already answered, you can get around this using a list comprehension. You could also use np.fromiter.

  • Related