- Trending Categories
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
Physics
Chemistry
Biology
Mathematics
English
Economics
Psychology
Social Studies
Fashion Studies
Legal Studies
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Functional Programming with purrr
Functional programming is a programming methodology in which we construct programs by constructing and applying functions. More specifically in programs, we apply sequential pure functions rather than statements. A pure function is a function that accepts an input and produces a consistent value as an output. Also, during this process no augment or input stream is modified. Such functions are capable of doing a single operation but for carrying out complex operations we can combine them into sequences.
In this tutorial, we will discuss functional programming using purr. Nowadays, Functional programming is important to master due to its capability to solve complex problems.
Functional programming in R
We can achieve functional programming in R using the purrr package. You can install the purrr package by using the below command in CRAN −
install.packages("purrr")
As you can see, we have installed purrr package successfully in our system.
Map_() family functions
The purrr package provides us map_() family functions using which we can achieve functional programming to get the same outcome of for and while loops.
The map_() function has several forms. Let’s see them one by one −
The map() function
Syntax
This is the most fundamental function. It accepts a vector and a function as a parameter and then calls the function for each element in the vector. The syntax of this function is given below,
map(vector, function)
It accepts a vector and a function as a parameter. It returns a list as an output.
Example
Consider a program given below,
# Import library library("purrr") # Create a vector myVector <- c(8, 3, 7, 2, 11, 20) # Define a function subtractByThree <- function(x) x - 3 # Print the output list print(map(myVector, subtractByThree))
Output
[[1]] [1] 5 [[2]] [1] 0 [[3]] [1] 4 [[4]] [1] -1 [[5]] [1] 8 [[6]] [1] 17
As you can see in the above, a list is produced after subtracting three from all the elements of the given vector.
Example
Now let us try to do the same thing again as we have done above but this time with loops. As you can see in the source code, this time it takes us to write more complex code in the case of loops.
# Create a vector myVector <- c(8, 3, 7, 2, 11, 20) # Create a list of size six subtractByThree <- vector("list", 6) # Iterate using a for loop # and calculate the result # for each value in the vector for(currentNumber in seq_along(myVector)){ subtractByThree[[currentNumber]] <- myVector[currentNumber] - 3 } # Print the list print(subtractByThree)
Output
[[1]] [1] 5 [[2]] [1] 0 [[3]] [1] 4 [[4]] [1] -1 [[5]] [1] 8 [[6]] [1] 17
As you can see above, a list is produced after subtracting three from all the elements of the given vector.
Therefore, we can say that using map() in code reduces the code size (as compared to loops), and also we don’t require to create an empty list to hold the results.
The map() function also provides us with simpler ways to extract elements from a vector on the basis of position and name. For example,
Example
In the following program, we have created a list of lists and we are accessing elements using the position first and then using the header name.
# Import the library library("purrr") # Create a list of lists myList <- list(list(data1 = 0.1, data2 = 1, data3 = "p"), list(data1 = 0.2, data2 = 4, data3 = "q"), list(data1 = 0.3, data2 = 8, data3 = "r") ) # Access using position map(myList, 2)
Output
[[1]] [1] 1 [[2]] [1] 4 [[3]] [1] 8
Access using header name
map(myList, "data3")
Output
[[1]] [1] "p" [[2]] [1] "q" [[3]] [1] "r"
As you can see above, second-position elements (using position) are printed first, and then the third-position (using header name) elements.
The map_chr() function
Syntax
As the name suggests, the map_char() function returns the atomic vector of strings. This function has the following syntax −
map_chr(vector, function)
It accepts a vector and a function as a parameter. It returns an atomic vector of strings.
Example
Let us consider a program illustrating the working of this function −
# Import library library("purrr") # Create a vector myVector <- c(8, 3, 7, 2, 11, 20) # Define a function subtractByThree <- function(x) x - 3 # Print the output list print(map_chr(myVector, subtractByThree))
Output
[1] "5.000000" "0.000000" "4.000000" "-1.000000" "8.000000" "17.000000"
As you can see in the output, the result of the operation is returned as a vector of strings.
The map_dbl() function
Syntax
As the name suggests, the map_dbl() function returns the atomic vector of double type. This function has the following syntax −
map_dbl(vector, function)
It accepts a vector and a function as a parameter. It returns an atomic vector of double type.
Example
Let us consider a program illustrating the working of this function −
# Import library library("purrr") # Create a vector myVector <- c(8, 3, 7, 2, 11, 20) # Define a function subtractByThree <- function(x) x - 3 # Print the output list print(map_dbl(myVector, subtractByThree))
Output
[1] 5 0 4 -1 8 17
As you can see in the output, the result of the operation is returned as a vector of double data type.
The reduce() Function
Syntax
Another motive of functional programming is to reduce. The purrr package provides us reduce() function using which we can reduce the number of values in a list to a single value. This function has the following syntax −
reduce(list, operation)
It accepts a list and the operation to be performed for the values of the list. It returns a single value.
Example
Let us consider the following program demonstrating the working of reduce() function −
# Import library library("purrr") # Apply reduce() function reduce(seq(1:10), `*`)
Output
[1] 3628800
As you can see above, we have applied multiply operation for all the elements of the list and a single value is produced as an output.
Troubleshooting Errors
The skill of troubleshooting issues in a particular program or software is quite important in the field of development. If there are lists involved in a program then it becomes more important because finding issues becomes tricky in the case of strings.
Map over safely() function
When we map over a list then sometimes the results of some operations don’t come as per the correct data type. More specifically the operation results in an invalid value. In such cases, we can use the safely() function to purrr safely.
In the following program, we are calculating the logarithmic value of all the elements of the list. But for -1 the log cannot be calculated. Therefore, it might raise some errors. But we are mapping using the safely() function here to get both results and errors during these operations. Since we want to pipe out results before getting any errors therefore we have applied the transpose() function.
Example
# Import library library("purrr") # Map using safely myList <- list(12, 11, 10, -1) %>% map(safely(log, otherwise = NA_real_)) %>% # Transpose the outcome transpose() # Print the result print(myList) # Print the result component print(myList[["Result"]]) # Print the error component print(myList[["Error"]])
Output
$result $result[[1]] [1] 2.484907 $result[[2]] [1] 2.397895 $result[[3]] [1] 2.302585 $result[[4]] [1] NaN $error $error[[1]] NULL $error[[2]] NULL $error[[3]] NULL $error[[4]] NULL
Print the result component
print(myList[["Result"]])
Output
NULL
Print the error component
print(myList[["Error"]])
Output
NULL
As you can see in the output, the log value of individual elements of the given list has been displayed. Since, the log of -1 in the list cannot be calculated therefore the corresponding output value has been replaced by NAN value. You can also see the result component and error components separately in the output.
Map over possibly() function
The possibly() function does the almost same task as the safely() function. The only difference is possibly() doesn’t print any error messages.
Example
Let us consider the program below −
# Import library library("purrr") # Map over possibly() myList <- list(12, 11, 10, -1) %>% map(possibly(function(data){ log(data) },NA_real_)) # Print the list print(myList)
Output
[[1]] [1] 2.484907 [[2]] [1] 2.397895 [[3]] [1] 2.302585 [[4]] [1] NaN
As you can see in the output, the log value of individual elements of the given list has been displayed. Since the log of -1 in the list cannot be calculated therefore the corresponding output value has been replaced by NAN.
Conclusion
In this tutorial, we discussed function programming using purrr package. We started with what is purrr package in R and how we can install it using CRAN, then we saw different versions of map functions and their working. In the end, we discussed troubleshooting methods using safely() and possibly() functions. I hope this tutorial will help you to enhance your knowledge in the field of data science.
- Related Articles
- Functional Programming Languages
- Functional Programming in Python
- Functional Interfaces in Java Programming
- Python Object-oriented and Functional Programming
- Breaking a loop in functional programming JavaScript.
- Continuing a loop in functional programming JavaScript.
- Explain the concepts of functional programming in JavaScript
- What is Non-Functional Testing? Types with Example
- Difference between Functional and Non-functional Testing
- Functional Currency
- Programming the 8259 with slaves
- Programming the 8259 with no slaves
- Beginning C# programming with Hello World
- Meta programming with Metaclasses in Python
- How can we use lambda expressions with functional interfaces in Java?
