Celso
Celso

Reputation: 659

Sorting only first character, along a specific order

I have a character vector like this:

stuff <- c("3S", "AH", "2I", "B4", "AL")

And I have a "position" vector like this:

pos <- c("3", "B", "A", "2")

I want to use the last vector as a reference to sort the first one by looking only at the first character of each element; I don't care about the second character. That is, I want to write and a function like specialsort(stuff, pos), and my result should be c("3S", "B4", "AH", "AL", "2I").

Upvotes: 6

Views: 597

Answers (4)

RoyalTS
RoyalTS

Reputation: 10203

I'm almost sure there's a simpler way to do it but this works:

specialsort <- function(stuff, pos) {
  stuff.pos <- sapply(pos,function(x) which(substring(stuff,1,1) == x))
  stuff[unlist(stuff.pos)]
}

specialsort(stuff,pos)

Careful though: This (and many other solutions) implicitly assumes that the pos vector is unique.

Upvotes: 2

Jealie
Jealie

Reputation: 6277

You can do it with a clever (if I may say myself) manipulation involving the transposition to factors:

stuff[order(factor(sapply(stuff,function(x)unlist(strsplit(x,''))[1]),levels=pos))]

edited to add some explanations and simplify:

The first part would be to isolate only the first character of your stuff vector. This can be done with:

> sapply(stuff,function(x)unlist(strsplit(x,''))[1])
 3S  AH  2I  B4  AL 
"3" "A" "2" "B" "A" 

Then, you can convert this to factors, using your vector pos as levels:

> factor(sapply(stuff,function(x)unlist(strsplit(x,''))[1]),levels=pos)
3S AH 2I B4 AL 
 3  A  2  B  A 
Levels: 3 B A 2

Finally, you can get the right order from these factors:

> order(factor(sapply(stuff,function(x)unlist(strsplit(x,''))[1]),levels=pos))
[1] 1 4 2 5 3

The finish is simply taking a subset from your original stuff vector:

> stuff[order(factor(sapply(stuff,function(x)unlist(strsplit(x,''))[1]),levels=pos))]
[1] "3S" "B4" "AH" "AL" "2I"

Upvotes: 0

dvdkamp
dvdkamp

Reputation: 156

try

stuff <- c("3S", "AH", "2I", "B4", "AL")
pos <- c("3", "B", "A", "2")

stuff.df = data.frame(stuff,pos = substr(stuff,1,1))
merge(data.frame(pos),stuff.df,sort = F)

The "pos" column of the sorted data.frame is what you want

Upvotes: 0

sgibb
sgibb

Reputation: 25736

You could use substring to extract the first letter of stuff and match to match your vector against the reference:

# find index in pos
i <- match(substring(stuff, 1, 1), pos)

# order by pos
o <- order(i)

stuff[o]
# [1] "3S" "B4" "AH" "AL" "2I"

Upvotes: 8

Related Questions