17  Basic Examples

This chapter provides more elaborated examples than the simple demos presented so far. The idea is to show you less abstract scenarios and cases where you could apply the functions and concepts covered so far.

17.1 Reversing A String

Our first example has to do with reversing a character string. More precisely, the objective is to create a function that takes a string and returns it in reversed order. The trick of this exercise depends on what we understand with the term reversing. For some people, reversing may be understood as simply having the set of characters in reverse order. For others, reversing may be understood as having a set of words in reverse order. Can you see the distinction?

Let’s consider the following two simple strings:

  • "atmosphere"
  • "the big bang theory"

The first string is formed by one single word (atmosphere). The second string is formed by a sentence with four words (the big bang theory). If we were to reverse both strings by characters we would get the following results:

  • "erehpsomta"
  • "yroeht gnab gib eht"

Conversely, if we were to reverse the strings by words, we would obtain the following output:

  • "atmosphere"
  • "theory bang big the"

For this example we will implement a function for each type of reversing operation.

17.2 Reversing a String by Characters

The first case for reversing a string is to do it by characters. This implies that we need to split a given string into its different characters, and then we need to concatenate them back together in reverse order. Let’s try to write a first function:

# function that reverses a string by characters
reverse_chars <- function(string)
{
  # split string by characters
  string_split = strsplit(string, split = "")
  # reverse order
  rev_order = nchar(string):1
  # reversed characters
  reversed_chars = string_split[[1]][rev_order]
  # collapse reversed characters
  paste(reversed_chars, collapse = "")
} 

Let’s test our reversing function with a character and numeric vectors:

# try 'reverse_chars'
reverse_chars("abcdefg")
[1] "gfedcba"
# try with non-character input
reverse_chars(12345)
Error in strsplit(string, split = ""): non-character argument

As you can see, reverse_chars() works fine when the input is in "character" mode. However, it complains when the input is "non-character". In order to make our function more robust, we can force the input to be converted as character. The resulting code is given as:

# reversing a string by characters
reverse_chars <- function(string)
{
  string_split = strsplit(as.character(string), split = "")
  reversed_split = string_split[[1]][nchar(string):1]
  paste(reversed_split, collapse = "")
} 

Now if we try our modified function, we get the expected results:

# example with one word
reverse_chars("atmosphere")
[1] "erehpsomta"
# example with a several words
reverse_chars("the big bang theory")
[1] "yroeht gnab gib eht"

Moreover, it also works with non-character input:

# try 'reverse_chars'
reverse_chars("abcdefg")
[1] "gfedcba"
# try with non-character input
reverse_chars(12345)
[1] "54321"

If we want to use our function with a vector (more than one element), we can combine it with the lapply() function as follows:

# reverse vector (by characters)
lapply(c("the big bang theory", "atmosphere"), reverse_chars)
[[1]]
[1] "yroeht gnab gib eht"

[[2]]
[1] "erehpsomta"

17.3 Reversing a String by Words

The second type of reversing operation is to reverse a string by words. In this case the procedure involves splitting up a string by words, re-arrange them in reverse order, and paste them back in one sentence. Here’s how we can defined our reverse_words() function:

# function that reverses a string by words
reverse_words <- function(string)
{
  # split string by blank spaces
  string_split = strsplit(as.character(string), split = " ")
  # how many split terms?
  string_length = length(string_split[[1]])
  # decide what to do
  if (string_length == 1) {
    # one word (do nothing)
    reversed_string = string_split[[1]]
  } else {
    # more than one word (collapse them)
    reversed_split = string_split[[1]][string_length:1]
    reversed_string = paste(reversed_split, collapse = " ")
  }
  # output
  return(reversed_string)
} 

The first step inside reverse_words() is to split the string according to a blank space pattern " ". Then we are counting the number of components resulting from the splitting step. Based on this information there are two options. If there is only one word, then there is nothing to do. If we have more than one words, then we need to re-arrenge them in reverse order and collapse them in a single string.

Once we have defined our function, we can try it on the two string examples to check that it works as expected:

# examples
reverse_words("atmosphere")
[1] "atmosphere"
reverse_words("the big bang theory")
[1] "theory bang big the"

Similarly, to use our function on a vector with more than one element, we should call it within the lapply() function as follows:

# reverse vector (by words)
lapply(c("the big bang theory", "atmosphere"), reverse_words)
[[1]]
[1] "theory bang big the"

[[2]]
[1] "atmosphere"

17.4 Names of Files

Imagine that you need to generate the names of 10 data .csv files. All the files have the same prefix name but each of them has a different number: file1.csv, file2.csv, … , file10.csv.

There are several ways in which you could generate a character vector with these names. One naive option is to manually type those names and form a vector with c()

c('file1.csv', 'file2.csv', 'file3.csv')
[1] "file1.csv" "file2.csv" "file3.csv"

But that’s not very efficient. Just think about the time it would take you to create a vector with 100 files. A better alternative is to use the vectorized nature of paste()

paste('file', 1:10, '.csv', sep = "")
 [1] "file1.csv"  "file2.csv"  "file3.csv"  "file4.csv"  "file5.csv" 
 [6] "file6.csv"  "file7.csv"  "file8.csv"  "file9.csv"  "file10.csv"

Or similarly with paste0()

paste0('file', 1:10, '.csv')
 [1] "file1.csv"  "file2.csv"  "file3.csv"  "file4.csv"  "file5.csv" 
 [6] "file6.csv"  "file7.csv"  "file8.csv"  "file9.csv"  "file10.csv"

17.5 Valid Color Names

R comes with the function colors() that returns a vector with the names (in English) of 657 colors available in R. How would you write a function is_color() to test if a given name—in English—is a valid R color. If the provided name is a valid R color, is_color() should return TRUE. If the provided name is not a valid R color is_color() should return FALSE.

is_color <- function(x) {
  x %in% colors()
}

Lets test it:

is_color('yellow')  # TRUE
[1] TRUE
is_color('blu')     # FALSE
[1] FALSE
is_color('turkuiose') # FALSE
[1] FALSE

Another possible way to write is_color() is comparing if any() element of colors() equals the provided name:

is_color2 <- function(x) {
  any(colors() == x)
}

Test it:

is_color2('yellow')  # TRUE
[1] TRUE
is_color2('blu')     # FALSE
[1] FALSE
is_color2('turkuiose') # FALSE
[1] FALSE