pythonRcpp
pythonRcpp

Reputation: 2146

Customised ordering according to column data in R

I have a csv file, which needs to be sorted according a column. The order however is taken from a order.cfg file. eg.my df looks like this

C1,C2,C3
A, 51,60
B, 91,10
M, 31,56
Z, 34,20

Now if order.cfg is like below

M
Z

Then df should be sorted in a way to push up M and Z up

C1,C2,C3
M, 31,56
Z, 34,20
A, 51,60
B, 91,10

I know how to order according to column values, but here it needs to be done through my configurable order.cfg.

One of my naive approach is to grep each element 1 by 1 in df.

  1. grep M in df$C1 take that row in newdf and remove from df
  2. rbind newdf with remainder of df

However there must be a better way to do this.

Upvotes: 0

Views: 32

Answers (2)

IRTFM
IRTFM

Reputation: 263471

I read these in as dataframes, 'df1' and 'order.cfg', with stringsAsFactors=FALSE. This then delivers the desired ordering:

> df1[ order(match(df1[[1]], order.cfg[[1]], incomparables=Inf) ),]
  C1 C2 C3
3  M 31 56
4  Z 34 20
1  A 51 60
2  B 91 10

Upvotes: 1

akrun
akrun

Reputation: 887851

If the order.cfg data is read as a vector ('v1') with two elements ('M', 'Z'), we change the 'C1' column in 'df1' to factor class by specifying the levels by concatenating (c) the elements that are common in the 'C1' and 'v1' (intersect(df1$C1, v1)), followed by the elements that are present in 'C1' and not in 'v1' (setdiff(df1$C1, v1)), order it and use that as index to reorder the rows of the 'df1'.

df2 <- df1[order(factor(df1$C1, levels=c(intersect(df1$C1,v1),
                                               setdiff(df1$C1, v1)))),]
row.names(df2) <- NULL
df2
#  C1 C2 C3
#1  M 31 56
#2  Z 34 20
#3  A 51 60
#4  B 91 10

data

v1 <- c('M', 'Z')

df1 <- structure(list(C1 = c("A", "B", "M", "Z"), C2 = c(51L, 91L, 31L, 
34L), C3 = c(60L, 10L, 56L, 20L)), .Names = c("C1", "C2", "C3"
), class = "data.frame", row.names = c(NA, -4L))

Upvotes: 0

Related Questions