Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Row wise Sorting in R

Tags:

r

I would like to how to do a row wise sorting in csv using R. Here's the following data I have

Name  English Math  French
John    56    78    86
Sam     79    97    86
Viru    93    44    34

I want to perform row wise sorting for the above dataset. Like the following.

Name  
John   French  86   Math 78  English 56 
Sam    Math    97   French 86 English 79  
Viru    English 93   Math 44   French 34

Please do let me know how to approach

like image 557
Ram Avatar asked Mar 09 '16 12:03

Ram


People also ask

How do I sort data by row in R?

To sort each row of an R data frame in increasing order, we can use apply function for sorting the columns and then transpose the output. For example, if we have a data frame called df that contains 5 columns then each row of df can be sorted in increasing order by using the command t(apply(df,1,sort)).

How do I sort a matrix row wise in R?

If we need only to sort by rows, use apply with MARGIN=1 and assign the output back to the original columns after transposing the output. NOTE: But we may need to change the column names as sorting by row gives the new sorted values.

How do I sort an order in R?

To sort a data frame in R, use the order( ) function. By default, sorting is ASCENDING. Prepend the sorting variable by a minus sign to indicate DESCENDING order.


2 Answers

If we need only to sort by rows, use apply with MARGIN=1 and assign the output back to the original columns after transposing the output.

df1[-1] <- t(apply(df1[-1], 1, 
        FUN=function(x) sort(x, decreasing=TRUE)))

df1
#   Name English Math French
# 1 John      86   78     56
# 2  Sam      97   86     79
# 3 Viru      93   44     34

NOTE: But we may need to change the column names as sorting by row gives the new sorted values.


Another option will be use apply separately to get the column names and the values, with Map we get the corresponding columns, cbind with the first column to have the output.

nMat <- `dim<-`(names(df1)[-1][t(apply(df1[-1], 1,  
        order, decreasing=TRUE))], dim(df1[-1]))
vMat <- t(apply(df1[-1], 1,  sort, decreasing=TRUE))
cbind(df1[1], data.frame(Map(cbind, as.data.frame(nMat,
   stringsAsFactors=FALSE), as.data.frame(vMat))))
#  Name    V1.1 V1.2   V2.1 V2.2    V3.1 V3.2
#1 John  French   86   Math   78 English   56
#2  Sam    Math   97 French   86 English   79
#3 Viru English   93   Math   44  French   34

Or another option is data.table. We melt the 'wide' format to 'long' format, grouped by 'Name', we order the 'value' in decreasing order in 'i', get the Subset of Data.table (.SD), create a new column ('N'), grouped by 'Name' and use dcast to convert from 'long' to 'wide'.

library(data.table)
dcast(melt(setDT(df1), id.var='Name')[order(-value), 
  .SD, Name][, N:=paste0("Col", 1:.N) , .(Name)],
    Name~N, value.var=c("variable", "value"))
#   Name variable_Col1 variable_Col2 variable_Col3 value_Col1 value_Col2 value_Col3
#1: John        French          Math       English         86         78         56
#2:  Sam          Math        French       English         97         86         79
#3: Viru       English          Math        French         93         44         34

EDIT: The above data.table solution will not work in case you have 10 or more columns with values, because then col10 will preceed col2 in the ordering, even though higher values will be stored in col2. To resolve this issue, you can use just number for the names of your new columns as in:

dcast(melt(setDT(df1), id.var='Name')[order(-value), 
      .SD, Name][, N:=1:.N , .(Name)],
        Name~N, value.var=c("variable", "value"))
like image 139
akrun Avatar answered Oct 04 '22 00:10

akrun


You can try:

cbind(x[1],matrix(paste(colnames(x)[apply(x[,2:4],1,order,decreasing=TRUE)+1],
      apply(x[,2:4],1,sort,decreasing=TRUE)),ncol=3,byrow=TRUE))
#  Name          1         2          3
#1 John  French 86   Math 78 English 56
#2  Sam    Math 97 French 86 English 79
#3 Viru English 93   Math 44  French 34
like image 44
nicola Avatar answered Oct 04 '22 00:10

nicola