Reputation: 2146
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.
However there must be a better way to do this.
Upvotes: 0
Views: 32
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
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
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