code: public static Frame sort(final Frame fr, int[] cols, int[] ascending) {
      if( cols.length==0 )        // Empty key list
        return fr;                // Return original frame
      for( int col : cols )
        if( col < 0 || col >= fr.numCols() )
          throw new IllegalArgumentException("Column "+col+" is out of range of "+fr.numCols());
      // All identity ID maps
      int id_maps[][] = new int[cols.length][];
      for( int i=0; i<cols.length; i++ ) {
        Vec vec = fr.vec(cols[i]);
        if( vec.isCategorical() ) {
          String[] domain = vec.domain();
          id_maps[i] = new int[domain.length];
          for( int j=0; j<domain.length; j++ ) id_maps[i][j] = j;
        }
      }
  
      return Merge.merge(fr, new Frame(new Vec[0]), cols, new int[0], true/*allLeft*/, id_maps, ascending, new int[0]);
    }
docs: It is not currently an in-place sort, so the data is doubled and a sorted copy is returned.