What's the difference between numpy.take and numpy.choose?

后端 未结 3 1379
清歌不尽
清歌不尽 2021-02-05 10:34

It seems that numpy.take(array, indices) and numpy.choose(indices, array) return the same thing: a subset of array indexed by indice

相关标签:
3条回答
  • 2021-02-05 11:00

    They are certainly not equivalent, as you can see by giving the same arguments (switched) to both methods:

    >>> a = np.array([[1, 2, 3, 4], 
                      [5, 6, 7, 8], 
                      [9, 10, 11, 12], 
                      [13, 14, 15, 16]])
    >>> np.choose([0, 2, 1, 3], a)
    array([ 1, 10,  7, 16]) # one from each row
    >>> np.take(a, [0, 2, 1, 3])
    array([1, 3, 2, 4]) # all from same row
    

    I suggest you read the documentation on take and choose.

    0 讨论(0)
  • 2021-02-05 11:00

    Explanation of np.choose() behavior in the documentation.

    • numpy.choose(a, choices, out=None, mode='raise')[source]
    np.choose(a,c) == np.array([c[a[I]][I] for I in ndi.ndindex(a.shape)])
    

    index array and choices

    import numpy as np
    
    print("--------------------------------------------------------------------------------")
    print("Index array 'a' and array of choice(s).")
    print("--------------------------------------------------------------------------------")
    a = np.array([4, 3, 2, 1])
    print("'a' is {} shape is {}\n".format(
        a, a.shape
    ))
        
    c = np.arange(60).reshape((5, 3, 4))
    _choice = c[0]
    print("An example choice is \n{} \nshape is {}\n".format(
        _choice,
        _choice.shape
    ))
    
    --------------------------------------------------------------------------------
    Index array 'a' and array of choice(s).
    --------------------------------------------------------------------------------
    'a' is [4 3 2 1] shape is (4,)
    
    An example choice is 
    [[ 0  1  2  3]
     [ 4  5  6  7]
     [ 8  9 10 11]] 
    shape is (3, 4)
    

    Broadcast

    Given an “index” array (a) of integers and a sequence of n arrays (choices), a and each choice array are first broadcast, as necessary, to arrays of a common shape; calling these Ba and Bchoices[i], i = 0,…,n-1 we have that, necessarily, Ba.shape == Bchoices[i].shape for each i.

    Ba.shape == Bchoices[i].shape.

    print("--------------------------------------------------------------------------------")
    print("np.choose() broadcasts 'a' and 'choice' to match (here only on a)")
    print("--------------------------------------------------------------------------------")
    a = np.vstack([
        np.array(a) for i in range(_choice.shape[0])
    ])
    print("Broadcast shape of 'a' is {}\n 'a' is \n{}\n.".format(a.shape, a))
    
    --------------------------------------------------------------------------------
    np.choose() broadcasts 'a' and 'choice' to match (here only on a)
    --------------------------------------------------------------------------------
    Broadcast shape of 'a' is (3, 4)
     'a' is 
    [[4 3 2 1]
     [4 3 2 1]
     [4 3 2 1]]
    

    Choose values from choices

    c[a[I]][I] for I in ndi.ndindex(a.shape)

    suppose that i (in that range) is the value at the (j0, j1, …, jm) position in Ba - then the value at the same position in the new array is the value in Bchoices[i] at that same position;

    print("--------------------------------------------------------------------------------")
    print("Simulate np.choose() behavior of choosing elements c[a[I]][I]]]:")
    print("np.array([ c[a[I]][I] for I in np.lib.index_tricks.ndindex(a.shape) ])")
    print("--------------------------------------------------------------------------------")
    result = np.array([]).astype(int)
    for I in np.lib.index_tricks.ndindex(a.shape):
        print("Selecting the element {} at c[{},{}]".format(
            c[a[I]][I].astype(int), a[I], I
        ))
        result = np.concatenate([result, [c[a[I]][I].astype(int)]])
        print("chosen items: {}".format(result))
        
    print("\nResult is \n{}\n".format(
        result.reshape(a.shape)
    ))
    
    --------------------------------------------------------------------------------
    Simulate np.choose() behavior of choosing elements c[a[I]][I]]]:
    np.array([ c[a[I]][I] for I in np.lib.index_tricks.ndindex(a.shape) ])
    --------------------------------------------------------------------------------
    Selecting the element 48 at c[4,(0, 0)]
    chosen items: [48]
    Selecting the element 37 at c[3,(0, 1)]
    chosen items: [48 37]
    Selecting the element 26 at c[2,(0, 2)]
    chosen items: [48 37 26]
    Selecting the element 15 at c[1,(0, 3)]
    chosen items: [48 37 26 15]
    Selecting the element 52 at c[4,(1, 0)]
    chosen items: [48 37 26 15 52]
    Selecting the element 41 at c[3,(1, 1)]
    chosen items: [48 37 26 15 52 41]
    Selecting the element 30 at c[2,(1, 2)]
    chosen items: [48 37 26 15 52 41 30]
    Selecting the element 19 at c[1,(1, 3)]
    chosen items: [48 37 26 15 52 41 30 19]
    Selecting the element 56 at c[4,(2, 0)]
    chosen items: [48 37 26 15 52 41 30 19 56]
    Selecting the element 45 at c[3,(2, 1)]
    chosen items: [48 37 26 15 52 41 30 19 56 45]
    Selecting the element 34 at c[2,(2, 2)]
    chosen items: [48 37 26 15 52 41 30 19 56 45 34]
    Selecting the element 23 at c[1,(2, 3)]
    chosen items: [48 37 26 15 52 41 30 19 56 45 34 23]
    
    Result is 
    [[48 37 26 15]
     [52 41 30 19]
     [56 45 34 23]]
    

    np.choose(a,c)

    print("--------------------------------------------------------------------------------")
    print("Run np.choose(a, c):")
    print("--------------------------------------------------------------------------------")
    print(np.choose(a, c))
    
    --------------------------------------------------------------------------------
    Run np.choose(a, c):
    --------------------------------------------------------------------------------
    [[48 37 26 15]
     [52 41 30 19]
     [56 45 34 23]]
    
    0 讨论(0)
  • 2021-02-05 11:09

    numpy.take(array, indices) and numpy.choose(indices, array) behave similarly on 1-D arrays, but this is just coincidence. As pointed out by jonrsharpe, they behave differently on higher-dimensional arrays.

    numpy.take

    numpy.take(array, indices) picks out elements from a flattened version of array. (The resulting elements are of course not necessarily from the same row.)

    For example,

    numpy.take([[1, 2], [3, 4]], [0, 3])
    

    returns

    array([1, 4])
    

    numpy.choose

    numpy.choose(indices, set_of_arrays) plucks out element 0 from array indices[0], element 1 from array indices[1], element 2 from array indices[2], and so on. (Here, array is actually a set of arrays.)

    For example

    numpy.choose([0, 1, 0, 0], [[1, 2, 3, 4], [4, 5, 6, 7]])
    

    returns

    array([1, 5, 3, 4])
    

    because element 0 comes from array 0, element 1 comes from array 1, element 2 comes from array 0, and element 3 comes from array 0.

    More Information

    These descriptions are simplified – full descriptions can be found here: numpy.take, numpy.choose. For example, numpy.take and numpy.choose behave similarly when indices and array are 1-D because numpy.choose first broadcasts array.

    0 讨论(0)
提交回复
热议问题