```# this first multisort was the original way I wrote it
# it could have a maximum of four columns to sort
# multisort<-function(frame, col1, dec1=F, col2, dec2=F, col3="", dec3=F, col4="", dec4=F){
# #there are three required arguments, frame, col1, and col2
# #this means you must have at least two columns from a dataset that you want to sort
#   if(col4=="") {
#     if(col3=="") {
#       #only have two columns to sort
#       sub<-frame[order(getVal(frame,col2),decreasing=dec2),]
#     } else {
#       #three columns to sort
#       sub<-multisort(frame,col2,dec2,col3,dec3)
#     }
#   } else {
#     #must sort all four columns
#     if(col3=="") {
#       #quit trying to mess up the function
#       sub<-multisort(frame,col2,dec2,col4,dec4)
#     }
#     sub<-multisort(frame,col2,dec2,col3,dec3,col4,dec4)
#   }
#   sub[order(getVal(sub,col1),decreasing=dec1),]
# }
#to sort just numeric values
#x[order(x\$SAL,-x\$AB),]

multisort<-function(frame, col1, dec1, col2, dec2, ...) {
#before doing any sorting, convert arguments into two vectors
mylist<-list(...)
col<-as.vector(c(col1,col2))
dec<-as.vector(c(dec1,dec2))
count<-6
for(i in mylist) {
if(i==TRUE || i==FALSE) {
if(count%%2==1) {
dec[count%/%2]<-i
count<-count+1
}
} else {
if(count%%2==0) { count<-count+1 }
else { count<-count+2 }
#set vectors, default dec to FALSE
col[count%/%2]<-i
dec[count%/%2]<-F
}
}
#the function parameters must be valid now
if(length(col)>2) {
extraArgs<-vector()
count<-1
for(i in col) {
pos=(count+1)%/%2
if(count>5) {
#append value to extraArgs
extraArgs[count-6]<-col[pos]
extraArgs[count-5]<-dec[pos]
}
count<-count+2
}
if(length(col)==3) {
sub<-multisort(frame,col[2],dec[2],col[3],dec[3])
} else {
sub<-multisort(frame,col[2],dec[2],col[3],dec[3],extraArgs)
}
} else {
#only two columns to sort - this is where the recursion ends!
sub<-frame[order(getVal(frame,col2),decreasing=dec2),]
}
sub[order(getVal(sub,col1),decreasing=dec1),]
}
getVal<-function(frame,col) {
eval(parse(text=paste(quote(frame),col,sep="\$")))
}

multisort(tmp,"CO",T,"SAL",F,"POS",T,"AB")
#there are a few rules to make sure this works
#you must set descending to T or F for the first two columns (3rd & 5th argument)
#don't set arguments equal to a variable name (except for the first 5 arguments)
#the 6th argument (assuming it's a legitimate column) will be set to col3 regardless if set to something in function call
```

• Another solution from Tatsuki Koyama -- much shorter R code which probably does the same thing:

```sort.mat3 <- function(mat, sort.by, decreasing = F){
# This will sort a matrix or a data.frame based on the columns 'sort.by.'
# 'sort.by' and 'decreasing' are  vectors of any length with length(sort.by) >= length(decreasing).

v <- rev(sort.by) ; de <- decreasing
if( length(de) < length(v) ){de[(length(de)+1) : length(v)] <- F}

for(i in 1:length(v)){
mat <- mat[order(mat[,v[i]], decreasing=rev(de)[i]),]}

mat}

# To reproduce Cole's example,
# > multisort(tmp,"CO",T,"SAL",F,"POS",T,"AB")
# do
sort.mat3(tmp, c(6,5,3), c(T, F, T))
# because "CO" is the 6th column, "SAL" is 5th and "POS" is 3rd column.
```
Edit | Attach | Print version | History: r2 < r1 | Backlinks | View wiki text | Edit WikiText | More topic actions...
Topic revision: r1 - 08 Nov 2006, TheresaScott

• Biostatistics Webs

Copyright © 2013-2022 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Vanderbilt Biostatistics Wiki? Send feedback