Replace letters with the appropriate set of letters

I ran into a minor problem and I did not find the right conditions for the search. I have letters from "A" - "N" and you want to replace them with more than "G" by "A" - "G" according to their position in the alphabet. using gsubas it seems bulky. Or is there some kind of regex that can make this smarter?

k <- rep(LETTERS[1:14],2)
gsub(pattern="H", replace="A", x=k)
gsub(pattern="I", replace="B", x=k)
gsub(pattern="J", replace="C", x=k)
gsub(pattern="K", replace="D", x=k)
# etc.

Can't I somehow convert the characters to an integer and then just calculate within integer values ​​and subsequently throw them back? Or are there any inverse to LETTERS? as.numeric()and as.integer()returns NA.

+5
source share
5 answers

This translates HN to AG:

chartr("HIJKLMN", "ABCDEFG", k)
+11

, , match:

AG <- LETTERS[1:7]
HN <- LETTERS[8:14]

k <- rep(LETTERS[1:14],2)
n <- AG[match(k, HN)]
ifelse(is.na(n), k, n)
# [1] "A" "B" "C" "D" "E" "F" "G" "A" "B" "C" "D" "E" "F" "G" "A" "B" "C" "D" "E"
#[20] "F" "G" "A" "B" "C" "D" "E" "F" "G"

LETTERS :

invLETTERS <- function(x) match(x, LETTERS[1:26])
invLETTERS(k)
# [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14  1  2  3  4  5  6  7  8  9 10 11
#[26] 12 13 14
+4

Here's a clean and simple solution:

k <- rep(LETTERS[1:14],2)

# (1) Create a lookup vector whose elements can be indexed into  
#     by their names and will return their associated values
subs <- setNames(rep(LETTERS[1:7], 2), LETTERS[1:14])
subs
#   A   B   C   D   E   F   G   H   I   J   K   L   M   N 
# "A" "B" "C" "D" "E" "F" "G" "A" "B" "C" "D" "E" "F" "G" 

# (2) Use it.
unname(subs[k])
#  [1] "A" "B" "C" "D" "E" "F" "G" "A" "B" "C" "D" "E" "F" "G"
# [15] "A" "B" "C" "D" "E" "F" "G" "A" "B" "C" "D" "E" "F" "G"
+4
source

I'm sure there is a way to make this more compact, but this is probably the thing you thought about in your second, non-regex idea:

k <- factor(k)
> k1 <- as.integer(k) %% 7
> k1[k1 == 0] <- 7
> LETTERS[k1]
 [1] "A" "B" "C" "D" "E" "F" "G" "A" "B" "C" "D" "E" "F" "G" "A" "B" "C" "D" "E" "F" "G" "A"
[23] "B" "C" "D" "E" "F" "G"

There is probably a smart way around the problem with number 0, but at the moment I don't feel terribly smart.

Edit

Good suggestions from the comments. First, for processing form 0, modular arithmetic:

k1 <- ((as.integer(k)-1) %%7) + 1

and in combination with matchit turns into a single line:

k1 <- LETTERS[((match(k, LETTERS)-1) %% 7) + 1]
+3
source

If your problem is only related to AN:

set.seed(1)
k = sample(LETTERS[1:14], 42, replace=TRUE)
temp = match(k, LETTERS)
# > table(k)
# k
# A B C D E F G I J K L M N 
# 2 2 5 2 1 6 3 3 5 4 3 3 3 
k[which(temp > 7)] = LETTERS[temp[temp > 7] -7]
# > table(k)
# k
# A  B  C  D  E  F  G 
# 2  5 10  6  4  9  6
+2
source

All Articles