Site icon R-bloggers

Readable code with base R (part 1)

[This article was first published on Roman Pahl, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
< section class="main-content">

Producing readable R code is of great importance, especially if there is a chance that you will share your code with people other than your future self. The now widely used magrittr pipe operator and dplyr tools are great frameworks for this purpose.

However, if you want to keep your dependencies on other packages at minimum, you may want to fall back to base R. In this series of blog posts, I will present some (maybe underused) base R tools for producing very readable R code.

In this post, we cover startsWith, endsWith, and Filter.

startsWith and endsWith for string-matching

There are special base functions for pre- or postfix matching.

# Basic usage:
w <- "Hello World!"
startsWith(w, "Hell")
## [1] TRUE
startsWith(w, "Helo")
## [1] FALSE
endsWith(w, "!")
## [1] TRUE

Of course, it also works with vectors. Can’t remember the exact name of a base function? Try this… 😉

base_funcs <- ls("package:base")

base_funcs[startsWith(base_funcs, "row")]
##  [1] "row"                    "row.names"             
##  [3] "row.names.data.frame"   "row.names.default"     
##  [5] "row.names<-"            "row.names<-.data.frame"
##  [7] "row.names<-.default"    "rowMeans"              
##  [9] "rownames"               "rownames<-"            
## [11] "rowsum"                 "rowsum.data.frame"     
## [13] "rowsum.default"         "rowSums"

The ‘readable’ property really shines when combined with control-flow.

tell_file_type <- function(fn) {
    # Check different file endings
    if (endsWith(fn, "txt")) {
        print("A text file.")
    }
    if (any(endsWith(fn, c("xlsx", "xls")))) {
        print("An Excel file.")
    }
}
tell_file_type("A.txt")
## [1] "A text file."
tell_file_type("B.xls")
## [1] "An Excel file."

The resulting code reads very well.

Filter

Using another nice base function, Filter, the above code can be further improved.

get_file_type <- function(fn) {
  file_endings <- c(text="txt", Excel="xls", Excel="xlsx")  
  Filter(file_endings, f = function(x) endsWith(fn, x))
}

get_file_type("C.xlsx")
##  Excel 
## "xlsx"

Again, very readable to my eyes. It should be noted that for this particular problem using tools::file_ext is even more appropriate, but I think the point has been made.

Last but not least, since Filter works on lists, you can use it on a data.frame as well.

dat <- data.frame(A=1:3, B=5:3, L=letters[1:3])
dat
##   A B L
## 1 1 5 a
## 2 2 4 b
## 3 3 3 c
Filter(dat, f = is.numeric)
##   A B
## 1 1 5
## 2 2 4
## 3 3 3
Filter(dat, f = Negate(is.numeric))  # or Filter(dat, f = function(x) !is.numeric(x))
##   L
## 1 a
## 2 b
## 3 c

That’s it for now – see you in part 2.

To leave a comment for the author, please follow the link and comment on their blog: Roman Pahl.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.