def sort! vector_order, opts={}
      raise ArgumentError, 'Required atleast one vector name' if vector_order.empty?

      # To enable sorting with categorical data,
      # map categories to integers preserving their order
      old = convert_categorical_vectors vector_order
      block = sort_prepare_block vector_order, opts

      order = @index.size.times.sort(&block)
      new_index = @index.reorder order

      # To reverse map mapping of categorical data to integers
      restore_categorical_vectors old

      @data.each do |vector|
        vector.reorder! order
      end

      self.index = new_index

      self
    end
def sort! vector_order, opts={}
      raise ArgumentError, 'Required atleast one vector name' if vector_order.empty?

      # To enable sorting with categorical data,
      # map categories to integers preserving their order
      old = convert_categorical_vectors vector_order
      block = sort_prepare_block vector_order, opts

      order = @index.size.times.sort(&block)
      new_index = @index.reorder order

      # To reverse map mapping of categorical data to integers
      restore_categorical_vectors old

      @data.each do |vector|
        vector.reorder! order
      end

      self.index = new_index

      self
    end
Sorts a dataframe (ascending/descending) in the given pripority sequence of
 vectors, with or without a block.

 @param vector_order [Array] The order of vector names in which the DataFrame
   should be sorted.
 @param opts [Hash] opts The options to sort with.
 @option opts [TrueClass,FalseClass,Array] :ascending (true) Sort in ascending
   or descending order. Specify Array corresponding to *order* for multiple
   sort orders.
 @option opts [Hash] :by (lambda{|a| a }) Specify attributes of objects to
   to be used for sorting, for each vector name in *order* as a hash of
   vector name and lambda expressions. In case a lambda for a vector is not
   specified, the default will be used.
 @option opts [TrueClass,FalseClass,Array] :handle_nils (false) Handle nils
   automatically or not when a block is provided.
   If set to True, nils will appear at top after sorting.

 @example Sort a dataframe with a vector sequence.


   df = Daru::DataFrame.new({a: [1,2,1,2,3], b: [5,4,3,2,1]})

   df.sort [:a, :b]
   # =>
   # <Daru::DataFrame:30604000 @name = d6a9294e-2c09-418f-b646-aa9244653444 @size = 5>
   #                   a          b
   #        2          1          3
   #        0          1          5
   #        3          2          2
   #        1          2          4
   #        4          3          1

 @example Sort a dataframe without a block. Here nils will be handled automatically.

   df = Daru::DataFrame.new({a: [-3,nil,-1,nil,5], b: [4,3,2,1,4]})

   df.sort([:a])
   # =>
   # <Daru::DataFrame:14810920 @name = c07fb5c7-2201-458d-b679-6a1f7ebfe49f @size = 5>
   #                    a          b
   #         1        nil          3
   #         3        nil          1
   #         0         -3          4
   #         2         -1          2
   #         4          5          4

 @example Sort a dataframe with a block with nils handled automatically.

   df = Daru::DataFrame.new({a: [nil,-1,1,nil,-1,1], b: ['aaa','aa',nil,'baaa','x',nil] })

   df.sort [:b], by: {b: lambda { |a| a.length } }
   # NoMethodError: undefined method `length' for nil:NilClass
   # from (pry):8:in `block in __pry__'

   df.sort [:b], by: {b: lambda { |a| a.length } }, handle_nils: true

   # =>
   # <Daru::DataFrame:28469540 @name = 5f986508-556f-468b-be0c-88cc3534445c @size = 6>
   #                    a          b
   #         2          1        nil
   #         5          1        nil
   #         4         -1          x
   #         1         -1         aa
   #         0        nil        aaa
   #         3        nil       baaa

 @example Sort a dataframe with a block with nils handled manually.

   df = Daru::DataFrame.new({a: [nil,-1,1,nil,-1,1], b: ['aaa','aa',nil,'baaa','x',nil] })

   # To print nils at the bottom one can use lambda { |a| (a.nil?)[1]:[0,a.length] }
   df.sort [:b], by: {b: lambda { |a| (a.nil?)?[1]:[0,a.length] } }, handle_nils: true

   # =>
   #<Daru::DataFrame:22214180 @name = cd7703c7-1dca-4560-840b-5ea51a852ef9 @size = 6>
   #                 a          b
   #      4         -1          x
   #      1         -1         aa
   #      0        nil        aaa
   #      3        nil       baaa
   #      2          1        nil
   #      5          1        nil