nodes: 0, module; 1, function_definition; 2, function_name:sortrows; 3, parameters; 4, block; 5, identifier:a; 6, default_parameter; 7, default_parameter; 8, default_parameter; 9, expression_statement; 10, expression_statement; 11, expression_statement; 12, comment:# We recursively call sortrows to make sure it is sorted best by every; 13, comment:# column; 14, if_statement; 15, if_statement; 16, identifier:i; 17, integer:0; 18, identifier:index_out; 19, False; 20, identifier:recurse; 21, True; 22, comment:""" Sorts array "a" by columns i
  
      Parameters
      ------------
      a : np.ndarray
          array to be sorted
      i : int (optional)
          column to be sorted by, taken as 0 by default
      index_out : bool (optional)
          return the index I such that a(I) = sortrows(a,i). Default = False
      recurse : bool (optional)
          recursively sort by each of the columns. i.e.
          once column i is sort, we sort the smallest column number
          etc. True by default.
  
      Returns
      --------
      a : np.ndarray
          The array 'a' sorted in descending order by column i
      I : np.ndarray (optional)
          The index such that a[I, :] = sortrows(a, i). Only return if
          index_out = True
  
      Examples
      ---------
      >>> a = array([[1,2],[3,1],[2,3]])
      >>> b = sortrows(a,0)
      >>> b
      array([[1, 2],
             [2, 3],
             [3, 1]])
      c, I = sortrows(a,1,True)
  
      >>> c
      array([[3, 1],
             [1, 2],
             [2, 3]])
      >>> I
      array([1, 0, 2])
      >>> a[I,:] - c
      array([[0, 0],
             [0, 0],
             [0, 0]])
      """; 23, assignment; 24, assignment; 25, binary_operator:recurse & (len(a[0]) > i + 1); 26, block; 27, identifier:index_out; 28, block; 29, else_clause; 30, identifier:I; 31, call; 32, identifier:a; 33, subscript; 34, identifier:recurse; 35, parenthesized_expression; 36, for_statement; 37, return_statement; 38, block; 39, attribute; 40, argument_list; 41, identifier:a; 42, identifier:I; 43, slice; 44, comparison_operator:len(a[0]) > i + 1; 45, identifier:b; 46, call; 47, block; 48, expression_list; 49, return_statement; 50, identifier:np; 51, identifier:argsort; 52, subscript; 53, call; 54, binary_operator:i + 1; 55, attribute; 56, argument_list; 57, expression_statement; 58, expression_statement; 59, expression_statement; 60, expression_statement; 61, identifier:a; 62, identifier:I; 63, identifier:a; 64, identifier:a; 65, slice; 66, identifier:i; 67, identifier:len; 68, argument_list; 69, identifier:i; 70, integer:1; 71, identifier:np; 72, identifier:unique; 73, subscript; 74, assignment; 75, assignment; 76, assignment; 77, assignment; 78, subscript; 79, identifier:a; 80, slice; 81, identifier:i; 82, identifier:ids; 83, comparison_operator:a[:, i] == b; 84, identifier:colids; 85, binary_operator:range(i) + range(i+1, len(a[0])); 86, pattern_list; 87, call; 88, subscript; 89, subscript; 90, identifier:a; 91, integer:0; 92, subscript; 93, identifier:b; 94, call; 95, call; 96, subscript; 97, identifier:I2; 98, identifier:sortrows; 99, argument_list; 100, identifier:I; 101, identifier:ids; 102, identifier:I; 103, subscript; 104, identifier:a; 105, slice; 106, identifier:i; 107, identifier:range; 108, argument_list; 109, identifier:range; 110, argument_list; 111, identifier:a; 112, call; 113, subscript; 114, integer:0; 115, True; 116, True; 117, subscript; 118, identifier:I2; 119, identifier:i; 120, binary_operator:i+1; 121, call; 122, attribute; 123, argument_list; 124, identifier:a; 125, call; 126, call; 127, integer:0; 128, identifier:i; 129, integer:1; 130, identifier:len; 131, argument_list; 132, identifier:np; 133, identifier:ix_; 134, identifier:ids; 135, identifier:colids; 136, attribute; 137, argument_list; 138, attribute; 139, argument_list; 140, subscript; 141, identifier:np; 142, identifier:ix_; 143, identifier:ids; 144, identifier:colids; 145, identifier:np; 146, identifier:nonzero; 147, identifier:ids; 148, identifier:a; 149, integer:0
code: def sortrows(a, i=0, index_out=False, recurse=True):
      """ Sorts array "a" by columns i
  
      Parameters
      ------------
      a : np.ndarray
          array to be sorted
      i : int (optional)
          column to be sorted by, taken as 0 by default
      index_out : bool (optional)
          return the index I such that a(I) = sortrows(a,i). Default = False
      recurse : bool (optional)
          recursively sort by each of the columns. i.e.
          once column i is sort, we sort the smallest column number
          etc. True by default.
  
      Returns
      --------
      a : np.ndarray
          The array 'a' sorted in descending order by column i
      I : np.ndarray (optional)
          The index such that a[I, :] = sortrows(a, i). Only return if
          index_out = True
  
      Examples
      ---------
      >>> a = array([[1,2],[3,1],[2,3]])
      >>> b = sortrows(a,0)
      >>> b
      array([[1, 2],
             [2, 3],
             [3, 1]])
      c, I = sortrows(a,1,True)
  
      >>> c
      array([[3, 1],
             [1, 2],
             [2, 3]])
      >>> I
      array([1, 0, 2])
      >>> a[I,:] - c
      array([[0, 0],
             [0, 0],
             [0, 0]])
      """
      I = np.argsort(a[:, i])
      a = a[I, :]
      # We recursively call sortrows to make sure it is sorted best by every
      # column
      if recurse & (len(a[0]) > i + 1):
          for b in np.unique(a[:, i]):
              ids = a[:, i] == b
              colids = range(i) + range(i+1, len(a[0]))
              a[np.ix_(ids, colids)], I2 = sortrows(a[np.ix_(ids, colids)],
                                                    0, True, True)
              I[ids] = I[np.nonzero(ids)[0][I2]]
  
      if index_out:
          return a, I
      else:
          return a