Question

I have a dataframe df :

V1  V2  V3
1   227 Day1
2   288 Day2
3   243 Day3
4   258 Day4
5   274 Day5
6   245 Day6
7   254 Day7
8   249 Day8
9   230 Day9
10  244 Day10

I want to subset df where V1 contains 5,1,7,3 in order. I used subset(df,V1 %in% c(5,1,7,3)) but what I am getting is:

V1  V2  V3
1   227 Day1
3   243 Day3
5   274 Day5
7   254 Day7

I want to maintain the order of rows in V1 to be 5,1,7,3 and not 1,3,5,7. How can I have the output to be:

V1  V2  V3
5   274 Day5
1   227 Day1
7   254 Day7
3   243 Day3
Was it helpful?

Solution

This is perhaps overcomplicated, but I would approach this task as follows:

An exemplary data frame:

(data2 <- data.frame(V1=1:10, V2=letters[1:10]))
##    V1 V2
## 1   1  a
## 2   2  b
## 3   3  c
## 4   4  d
## 5   5  e
## 6   6  f
## 7   7  g
## 8   8  h
## 9   9  i
## 10 10  j

Let's find in which row we have a match (NA - no match, i - i-th value was matched):

(m <- match(data2$V1, c(5,1,7,3)))
##  [1]  2 NA  4 NA  1 NA  3 NA NA NA

Now we select matching rows matches and permute them accordingly:

data2[!is.na(m),][order(na.omit(m)),]
##   V1 V2
## 5  5  e
## 1  1  a
## 7  7  g
## 3  3  c

On the other hand, if you know that V1 consists of consecutive natural numbers (starting from 1), the solution is easy as 1-2-3:

data2[c(5,1,7,3),]
##   V1 V2
## 5  5  e
## 1  1  a
## 7  7  g
## 3  3  c

OTHER TIPS

You can use merge with sort=FALSE and it seems to return in the order that it matches. It will also work if you have repeated values in V1. E.g.:

dat <- data.frame(V1=1:10, V2=letters[1:10])
dat$V1[8] <- 5

dat
#   V1 V2
#1   1  a
#2   2  b
#3   3  c
#4   4  d
#5   5  e
#6   6  f
#7   7  g
#8   5  h
#9   9  i
#10 10  j

merge(data.frame(V1=c(5,1,7,3)),dat,by="V1",sort=FALSE)

#  V1 V2
#1  5  e
#2  5  h
#3  1  a
#4  7  g
#5  3  c
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top