#' Rename the elements of the input by the new set of names
#' given in the table n2o or by the consecutive numbers.
#'
#' @param old An object whose elements are to be replaced by numbers.
#' @param n2o Conversion table (data frame) from old to new or NULL. \cr
#' Must have two columns named "new" and "old" and "new" must be 1:nrow(n2o).
#' @param sort = 1 to sort the new name when n2o is NULL. \cr
#' = 2 to sort  the new name when n2o is NULL by naturalsort package.
#' @param print = 1 to print the conversion summary.
#'
#' @return A list of the following: \cr
#'   new     renamed version of old:  same shape and same order as old \cr
#'   n2o     conversion table from new to old \cr
#'   o2n     sorted version of n2o by old \cr
#'   freqnew frequency of new names \cr
#'           cbind( n2o,freqnew) will give you the frequency table. \cr
#'   od      order to be used to sort an object
#'
#' @details
#' By default, the unique names in old will be renamed by the
#' consecutive numbers in the order of appearance. \cr
#' When old is a data frame, new may be a matrix.
#' \cr\cr
#' naturalsort package is required to use sort=2 option.
#' \cr\cr
#' 
#' @examples
#' # add consecutive numbers in the order of appearance.
#' ( new_name( matrix(c("IA","NY","WY","AR","NY","IA"),3) ) )
#'
#' # renaming old
#' seed <- 1701; set.seed(seed)
#' old <- sample( letters[1:6], 10, replace=TRUE )
#' # order of appearance
#' res1 <- new_name( old, print=1 )
#' # sorted order
#' res2 <- new_name( old, print=1, sort=1)
#' # using renaming table
#' old2 <- sample( old, 10, replace=TRUE )
#' res <- new_name( old2, res2$n2o, print=1 )
#'
#' # Rename "a" as "Z", "b" as "Y", "c" as "X".
#' new <- c( "Z", "Y", "X" )
#' old <- c( "a", "b", "c" )
#' n2o <- data.frame( new=new, old=old, stringsAsFactors=0 )
#' temp <- new_name( old, n2o )
#' Print( old, temp$new )
#' old2 <- sample( old,10,replace=1 )
#' temp2 <- new_name( old2, n2o )
#' Print( old2, temp2$new  )
#'
#' # sorting vectors
#' # Suppose that you hava a vector
#' #   vec = c( "A", "D", "B", "E", "C", "D", "A" )
#' # and you wish to sort it as
#' #  vec_sorted <- vec[od,]
#' # so that
#' #  vec_sorted = c("B", "D", "D", "A", "A", "C", "E") .
#' # This can be accomplished by using order2 function as:
#' # vec <- c( "A", "D", "B", "E", "C", "D", "A" )
#' # od <- order2( vec, order=c("B", "D", "A", "C", "E") )
#' # vec_sorted <- vec[od]
#' #
#' # The same result can be obtained as:#'
#' vec <- c( "A", "D", "B", "E", "C", "D", "A" )
#' n2o=data.frame(new=1:5, old=c("B", "D", "A", "C", "E"))
#' od <- new_name( vec, n2o )$od
#' vec_sorted <- vec[od]
#'
#'
#'
#' @export
#'

new_name <- function( old, n2o=NULL, sort=0, print=0 ){
 # assign consecutive numbers to the unique elements of old
 # Shin-ichi Mayekawa
 # 20150430 DNC, 0502
 # naturalsort: 20150508
 # factor input: 20150811
 # typo fix: 20160801
 # return od: 20160804
 # when new is a factor: 20160805
 # freqnew: 20161003
 # roxgen2: 20170926
 # bugfix: 20170927
 # roxygen2 error fixed: 20191129dnc
 #
 #
 # Args:
 #
 #   old     vector or matrix which contains old names
 #
 #   n2o     optional matrix or data.frame which contains new and old
 #           where old[i] will be renamed as new[i].
 #
 #   sort    = 1 to assign consecutive numbers to the sorted elements of old.
 #           = 2 to use package naturalsort
 #
 #
 # Values: list of the following
 #
 #   new     renumbered version of old:  same shape and same order as old
 #   n2o     conversion table from new to old
 #   o2n     sorted version of n2o by old
 #   freqnew frequency vector of new names
 #
 # Needs:
 #
 #   naturalsort package
 #

 # original data type
 if( is.factor(old) ){
  old=as.vector(old)
  type=1; nr=length(old); nc=1
 }
 if( is.vector(old) ){
  type=1; nr=length(old); nc=1
 }
 else if( is.matrix(old) ){
  type=2;  nr=nrow(old); nc=ncol(old)
 }
 else if( is.data.frame(old)){
  type=2;  nr=nrow(old); nc=ncol(old)
  for( j in 1:nc ){
   if( is.factor(old[,j]) ) old[,j]=as.vector(old[,j])
  }
 }

 # vectorize
 old=c(as.matrix(old))

 # conversion table
 if( is.null(n2o) ){
  n2oin=0
  oldu=unique(old)
  if( sort == 1 ) oldu=sort(oldu)
  else if( sort == 2 ) oldu=naturalsort(oldu)
  n=length(oldu)
  n2o=data.frame( new=1:n, old=oldu, stringsAsFactors=0 )
 }
 else{

  n2oin=1
  n2o=as.data.frame(n2o)
  n=nrow(n2o)

  # Print(loceq(old,n2o[,2]), old%in%n2o[,2])
  if( !all( old %in% n2o[,2] ) ){
   cat("\nerror1:(new_name)"
       , " Given conversion table is not sufficient for the new input.\n")
   Print(old,n2o)
   stop()
  }

 }

 # rename old by new
 # add tempid
 old=data.frame( old=old, tempid=1:length(old), stringsAsFactors=0 )
 # merge df n2o and df old by var old as key
 new=merge( n2o, old, by="old", sort=FALSE, stringsAsFactors=0 )
 # sort back to the original order
 new=new[order(new$tempid),]
 # back to original mode
 if( type == 1 ) new=c(as.vector(new$new))
 else if( type == 2 ) new=matrix(as.vector(new$new),nr)

 # freq
 freqnew=c( tapply( new, new, function(x) length(x) ) ) # This keeps the names!


 if( print ){
  tt=c("vector", "matrix"); n2oin1=c("not given","given")
  cat("\nRenaming the elements of old using the table given in n2o.\n")
  cat(" type of old =", tt[type], "\n")
  cat(" total # of elements in old =", nr, "\n")
  cat(" # of unique elements of old =", n, "\n")
  cat(" Conversion table from old to in is ",n2oin1[n2oin+1],".\n")
  if( n2oin == 0 ) cat(" sort option =", sort, "\n")
  cat(" Conversion table\n")
  Print(n2o)
  cat(" Input (old) and Output (new) \n")
  res=data.frame(matrix(old[,-ncol(old)],nr),new, stringsAsFactors=0)
  if( type == 1 ) colnames(res)=c("old","new")
  else colnames(res)=c(paste("old",1:nc,sep=""),paste("new",1:nc,sep=""))
  print(res)
 }

 o2n=n2o[order(n2o$old),]
 res=list( new=new, n2o=n2o, o2n=o2n, freqnew=freqnew, od=order(new) )
 return( res )

} # end of new_name


