def at *positions
      if AXES.include? positions.last
        axis = positions.pop
        return row_at(*positions) if axis == :row
      end

      original_positions = positions
      positions = coerce_positions(*positions, ncols)
      validate_positions(*positions, ncols)

      if positions.is_a? Integer
        @data[positions].dup
      else
        Daru::DataFrame.new positions.map { |pos| @data[pos].dup },
          index: @index,
          order: @vectors.at(*original_positions),
          name: @name
      end
    end
def at *positions
      if AXES.include? positions.last
        axis = positions.pop
        return row_at(*positions) if axis == :row
      end

      original_positions = positions
      positions = coerce_positions(*positions, ncols)
      validate_positions(*positions, ncols)

      if positions.is_a? Integer
        @data[positions].dup
      else
        Daru::DataFrame.new positions.map { |pos| @data[pos].dup },
          index: @index,
          order: @vectors.at(*original_positions),
          name: @name
      end
    end
Retrive vectors by positions
 @param [Array<Integer>] positions of vectors to retrive
 @return [Daru::Vector, Daru::DataFrame] vector for single position and dataframe for multiple positions
 @example
   df = Daru::DataFrame.new({
     a: [1, 2, 3],
     b: ['a', 'b', 'c']
   })
   df.at 0
   # => #<Daru::Vector(3)>
   #       a
   #   0   1
   #   1   2
   #   2   3