How can I get the last n characters from a string in R? Is there a function like SQL's RIGHT?
15 Answers
I'm not aware of anything in base R, but it's straight-forward to make a function to do this using substr and nchar:
x <- "some text in a string"
substrRight <- function(x, n){
  substr(x, nchar(x)-n+1, nchar(x))
}
substrRight(x, 6)
[1] "string"
substrRight(x, 8)
[1] "a string"
This is vectorised, as @mdsumner points out. Consider:
x <- c("some text in a string", "I really need to learn how to count")
substrRight(x, 6)
[1] "string" " count"
 
    
    - 176,377
- 47
- 447
- 496
- 
                    1Use stringi package. It works fine with NAs and all encoding :) – bartektartanus Mar 12 '14 at 20:20
- 
                    3Would it be more efficient to avoid calling `nchar(x)` twice by assigning it to a local variable? – Dave Jarvis Aug 12 '17 at 03:24
- 
                    have been looking for this for a while! – stats_noob Jul 30 '22 at 04:10
- 
                    No mention of which package substrRight is from? – Blaiso Mar 22 '23 at 19:34
If you don't mind using the stringr package, str_sub is handy because you can use negatives to count backward:
x <- "some text in a string"
str_sub(x,-6,-1)
[1] "string"
Or, as Max points out in a comment to this answer,
str_sub(x, start= -6)
[1] "string"
 
    
    - 10,199
- 6
- 44
- 78
- 
                    45
- 
                    2stringr doesn't work well with NA's value and all encoding. I strongly reccomend stringi package :) – bartektartanus Mar 12 '14 at 20:19
- 
                    3I believe `stringr` had been remade using `stringi` as a backend, so should work with NAs etc. now. – m-dz Jul 11 '16 at 10:09
Use stri_sub function from stringi package.
To get substring from the end, use negative numbers.
Look below for the examples:
stri_sub("abcde",1,3)
[1] "abc"
stri_sub("abcde",1,1)
[1] "a"
stri_sub("abcde",-3,-1)
[1] "cde"
You can install this package from github: https://github.com/Rexamine/stringi
It is available on CRAN now, simply type
install.packages("stringi")
to install this package.
 
    
    - 365
- 1
- 10
 
    
    - 15,284
- 6
- 74
- 102
Another reasonably straightforward way is to use regular expressions and sub:
sub('.*(?=.$)', '', string, perl=T)
So, "get rid of everything followed by one character". To grab more characters off the end, add however many dots in the lookahead assertion:
sub('.*(?=.{2}$)', '', string, perl=T)
where .{2} means .., or "any two characters", so meaning "get rid of everything followed by two characters".
sub('.*(?=.{3}$)', '', string, perl=T)
for three characters, etc. You can set the number of characters to grab with a variable, but you'll have to paste the variable value into the regular expression string:
n = 3
sub(paste('.+(?=.{', n, '})', sep=''), '', string, perl=T)
 
    
    - 483
- 4
- 5
- 
                    5To avoid all the look-aheads etc, you could just do `regmatches(x, regexpr(".{6}$", x))` – thelatemail Jul 13 '16 at 04:15
A simple base R solution using the substring() function (who knew this function even existed?):
RIGHT = function(x,n){
  substring(x,nchar(x)-n+1)
}
This takes advantage of basically being substr() underneath but has a default end value of 1,000,000.
Examples:
> RIGHT('Hello World!',2)
[1] "d!"
> RIGHT('Hello World!',8)
[1] "o World!"
 
    
    - 2,612
- 2
- 20
- 35
Try this:
x <- "some text in a string"
n <- 5
substr(x, nchar(x)-n, nchar(x))
It shoudl give:
[1] "string"
UPDATE: as noted by mdsumner, the original code is already vectorised because substr is. Should have been more careful.
And if you want a vectorised version (based on Andrie's code)
substrRight <- function(x, n){
  sapply(x, function(xx)
         substr(xx, (nchar(xx)-n+1), nchar(xx))
         )
}
> substrRight(c("12345","ABCDE"),2)
12345 ABCDE
 "45"  "DE"
Note that I have changed (nchar(x)-n) to (nchar(x)-n+1) to get n characters.
An alternative to substr is to split the string into a list of single characters and process that: 
N <- 2
sapply(strsplit(x, ""), function(x, n) paste(tail(x, n), collapse = ""), N)
 
    
    - 29,099
- 6
- 83
- 91
I use substr too, but in a different way. I want to extract the last 6 characters of "Give me your food." Here are the steps:
(1) Split the characters
splits <- strsplit("Give me your food.", split = "")
(2) Extract the last 6 characters
tail(splits[[1]], n=6)
Output:
[1] " " "f" "o" "o" "d" "."
Each of the character can be accessed by splits[[1]][x], where x is 1 to 6.
 
    
    - 2,251
- 22
- 28
someone before uses a similar solution to mine, but I find it easier to think as below:
> text<-"some text in a string" # we want to have only the last word "string" with 6 letter
> n<-5 #as the last character will be counted with nchar(), here we discount 1
> substr(x=text,start=nchar(text)-n,stop=nchar(text))
This will bring the last characters as desired.
 
    
    - 41
- 3
For those coming from Microsoft Excel or Google Sheets, you would have seen functions like LEFT(), RIGHT(), and MID(). I have created a package known as forstringr and its development version is currently on Github.
if(!require("devtools")){
 install.packages("devtools")
}
devtools::install_github("gbganalyst/forstringr")
library(forstringr)
- the - str_left(): This counts from the left and then extract n characters
- the - str_right()- This counts from the right and then extract n characters
- the - str_mid()- This extract characters from the middle
Examples:
x <- "some text in a string"
str_left(x, 4)
[1] "some"
str_right(x, 6)
[1] "string"
str_mid(x, 6, 4)
[1] "text"
 
    
    - 364
- 4
- 8
I used the following code to get the last character of a string.
    substr(output, nchar(stringOfInterest), nchar(stringOfInterest))
You can play with the nchar(stringOfInterest) to figure out how to get last few characters.
 
    
    - 29
- 6
A little modification on @Andrie solution gives also the complement:
substrR <- function(x, n) { 
  if(n > 0) substr(x, (nchar(x)-n+1), nchar(x)) else substr(x, 1, (nchar(x)+n))
}
x <- "moSvmC20F.5.rda"
substrR(x,-4)
[1] "moSvmC20F.5"
That was what I was looking for. And it invites to the left side:
substrL <- function(x, n){ 
  if(n > 0) substr(x, 1, n) else substr(x, -n+1, nchar(x))
}
substrL(substrR(x,-4),-2)
[1] "SvmC20F.5"
 
    
    - 1,663
- 1
- 17
- 28
Just in case if a range of characters need to be picked:
# For example, to get the date part from the string
substrRightRange <- function(x, m, n){substr(x, nchar(x)-m+1, nchar(x)-m+n)}
value <- "REGNDATE:20170526RN" 
substrRightRange(value, 10, 8)
[1] "20170526"
 
    
    - 853
- 10
- 34
 
     
     
     
     
    