Skip to Content

Fun with lists (in R)

Table of Contents

I came across this post by Matthias Eisen which contains some useful snippets to work with lists in Python. Inspired by the same, I decided to document some R functions for a similar set of operations. Though some of them are simple, one liners, I learned a trick or two while creating this list.

A list in python resembles closely with a vector in R which is a homogenous(members of same type) 1 dimensional data structure. A list in R is a hetrogenous(can have members of different types) data structure or can be thought of as a structure that may contain object of any other types. Most functions below are written for vectors, though can be extended easily for lists as well.

1 Removing Elements

1.1 All values equal to x

x <- 4
a <- c(1L, 2L, 3L, 4L, 4L, 5L, 6L, 1L, 4L)
print(a[a != x])

[1] 1 2 3 5 6 1

1.2 Duplicates

a <- c(1L, 2L, 3L, 4L, 4L, 5L, 6L, 1L, 4L)
print(unique(a))

[1] 1 2 3 4 5 6

a <- c(1L, 2L, 3L, 4L, 4L, 5L, 6L, 1L, 4L)
row.names(table(a))

[1] “1” “2” “3” “4” “5” “6”

1.3 First element

a <- c(1L, 2L, 3L, 4L, 4L, 5L, 6L, 1L, 4L)
print(a[2:length(a)])

[1] 2 3 4 4 5 6 1 4

a <- c(1L, 2L, 3L, 4L, 4L, 5L, 6L, 1L, 4L)
print(a[-1])

[1] 2 3 4 4 5 6 1 4

1.4 Last element

a <- c(1L, 2L, 3L, 4L, 4L, 5L, 6L, 1L, 4L)
print(a[1:(length(a) - 1)])

[1] 1 2 3 4 4 5 6 1

a <- c(1L, 2L, 3L, 4L, 4L, 5L, 6L, 1L, 4L)
print(a[-length(a)])

[1] 1 2 3 4 4 5 6 1

1.5 nth element

n <- 3
a  <-  c(1L, 2L, 3L, 4L, 5L, 6L)
print(a[c(1:(n - 1), (n + 1):length(a))])

n <- 3
a  <-  c(1L, 2L, 3L, 4L, 5L, 6L)
r <- c()
for (i in seq_along(a)) {
  if (i != n)
    r <- c(r, a[[i]])
}
print(r)

[1] 1 2 4 5 6

2 Replacing Elements

2.1 All values equal to x

x <-  4
a <- c(1L, 2L, 3L, 44L, 4L, 5L, 6L, 1L, 4L)
a[a==x] <- 0
print(a)

[1] 1 2 3 44 0 5 6 1 0

x <-  4
a <- c(1L, 2L, 3L, 44L, 4L, 5L, 6L, 1L, 4L)
print(as.numeric(gsub(x,0,a)))
# print(as.numeric(sub(x,0,a))) - Do you know the difference ?

[1] 1 2 3 0 0 5 6 1 0

2.2 First element

a <- c(1L, 2L, 3L, 4L, 4L, 5L, 6L, 1L, 4L)
a[1] <- 0
print(a)

[1] 0 2 3 4 4 5 6 1 4

a <- c(1L, 2L, 3L, 4L, 4L, 5L, 6L, 1L, 4L)
print(c(0,a[2:length(a)]))

[1] 0 2 3 4 4 5 6 1 4

2.3 Last element

a <- c(1L, 2L, 3L, 4L, 4L, 5L, 6L, 1L, 4L)
a[length(a)] <- 0
print(a)

[1] 1 2 3 4 4 5 6 1 0

a <- c(1L, 2L, 3L, 4L, 4L, 5L, 6L, 1L, 4L)
print(c(a[1:(length(a)-1)],0))

[1] 1 2 3 4 4 5 6 1 0

2.4 nth element

n  <-  3
a  <-  c(1L, 2L, 3L, 4L)
a[n] <- 0
print(a)

[1] 1 2 0 4

n  <-  3
a  <-  c(1L, 2L, 3L, 4L)
for(i in seq_along(a)){
  if(i == n){
    a[i] <- 0
  }
}
print(a)

[1] 1 2 0 4

3 Sorting

3.1 Alphabetically

a  <- c("d", "C", "B", "a")
print(sort(a))

[1] “a” “B” “C” “d”

a  <- c("d", "C", "B", "a")
print(a[order(a)])

[1] “a” “B” “C” “d”

3.2 Alphabetically (case-sensitive) - Work out

3.3 Strings by length

a <- c("aaaa", "B", "CCC", "dd")
names(sort(vapply(a,nchar,1)))

[1] “B” “dd” “CCC” “aaaa”

4 Other

4.1 Add up all values in a vector of numbers

a <-  c(1, 2.5, 7, 13221, 4.6545)
b <-  sum(a)
print(b)

[1] 13236.15

4.2 Append to a list

a <- c(1L, 2L, 3L)
a <- c(a,4L)
print(a)

[1] 1 2 3 4

4.3 Apply a function to every vector element

## Declaring functions
echo_fun <- function(x){return(x)}
sq_fun <- function(x){return(x^2)}  
a <- c(1L, 2L, 3L)
vapply(a,sq_fun,1)

[1] 1 4 9

unlist(purrr::map(a,sq_fun))

[1] 1 4 9

4.4 Cartesian product of n lists

a <- c(1L, 2L, 3L)
b <- c(4L, 5L, 6L)
c <- c(7L, 8L, 9L)
expand.grid(a,b,c)

4.5 Check if 2 lists have at least 1 common element

a <- c(1L, 2L, 0L)
b <- c(3L, 1L, 4L)

ifelse(length(intersect(a,b)) > 0,TRUE,FALSE)

[1] TRUE

4.6 Check if a list contains the value x

a <- c(1, 2.5, 7, 13221, 4.6545)
if(7  %in%  a) print('yes') else print('no')

[1] “yes”

4.7 Count the number of times x appears in a list

a <- c(1, 2.5, 7, 13221, 4.6545, 7)
as.vector(table(a[a==7]))

[1] 2

4.8 Difference of 2 lists

a <- c(1L, 2L, 3L, 4L)
b <- c(3L, 4L, 5L, 6L)
setdiff(a,b)

[1] 1 2

4.9 Difference of n lists

a  <- c(1L, 2L, 3L, 4L)
b <-  list(c(3L, 5L, 6L, 7L), c(1L, 8L, 9L, 10L))

# To solve - a - b[[1]] - b[[2]]
for(i in seq_along(b)){
  if(i == 1){
    diff_list <- setdiff(a,b[[i]])  
  } else {
    diff_list <- setdiff(diff_list,b[[i]])  
  }
}
print(diff_list)

[1] 2 4

4.10 First n elements of a list

n <- 2
a <- c(1L, 2L, 3L, 4L, 5L, 6L)
print(a[1:n])

[1] 1 2

4.11 First n non-x elements of a list

n <- 3
x <-  2
a <- c(1L, 2L, 2L, 3L, 2L, 2L, 2L, 4L, 5L, 6L)
b <- a[a != x]
print(b[1:n])

[1] 1 3 4

4.12 Flatten a list of lists

a  <-  list(c(1L, 2L, 3L), c(4L, 5L, 6L), c(7L, 8L, 9L))
print(unlist(a))

[1] 1 2 3 4 5 6 7 8 9

4.13 Insert x after the first occurence of y

x <-  4
y <-  6
a <- c(1L, 2L, 3L, 5L, 3L, 6L, 2L)
b <- tryCatch({
  pos <- which(a == y)[[1]]
  a <- c(a[1:pos], x, a[(pos + 1):length(a)])
},
error = function(e) {
  c(a,x)
})
print(b)

[1] 1 2 3 5 3 6 4 2

4.14 Iterate over every other element of a list

a <- c(1L, 2L, 3L, 4L, 5L, 6L)
print(a[seq(1,length(a),2)])

[1] 1 3 5

4.15 Iterate over index/value pairs of a list

a <- c(1, 2.5, 7, 13221, 4.6545)
for(i in seq_along(a)){
  print(glue::glue("{i}: {a[[i]]}"))
}

1: 1

2: 2.5

3: 7

4: 13221

5: 4.6545

4.16 Iterate over the elements of a list

a <- c(1L, 2L, 3L, 4L)
for(x in a){
  print(x)
} 

1

2

3

4

4.17 Permutations of list elements

x <- c('a','b','c')

all_combinations <- function(vector_to_permute){
  label_list <- seq(1,length(vector_to_permute))
  y <- data.frame(permute::allPerms(label_list))
  for(i in 1:nrow(y)){
    for(j in 1:ncol(y)){
      y[i,j] <- vector_to_permute[label_list == y[i,j]]
    }
  }
  z <- c(paste0(vector_to_permute,collapse = ''),apply(y, 1, paste0, collapse = ''))
  return(z)
}

print(all_combinations(x))

[1] “abc” “acb” “bac” “bca” “cab” “cba”

4.18 Reverse the order of a list

a <- c(1L, 2L, 3L, 4L)
print(a[length(a):1])

[1] 4 3 2 1

4.19 Symmetric difference of 2 lists

a <- c(1L, 2L, 3L, 4L)
b <- c(3L, 4L, 5L, 6L)

print(c(setdiff(a,b),setdiff(b,a)))

[1] 1 2 5 6

4.20 Symmetric difference of n lists

a  <-  list(c(1L, 2L, 3L, 4L), c(3L, 4L, 5L, 6L), c(1L, 5L, 7L, 8L))
b <- unlist(a)
c <- table(b)
print(as.numeric(names(c)[c == 1]))

[1] 2 6 7 8

library(magrittr)
a  <-  list(c(1L, 2L, 3L, 4L), c(3L, 4L, 5L, 6L), c(1L, 5L, 7L, 8L))
x <- unlist(a) %>% table %>% data.frame %>% dplyr::filter(`Freq` == 1)
print(as.numeric(as.character(x[,1])))

[1] 2 6 7 8

4.21 Union of 2 lists

a <- c(1L, 2L, 3L, 4L)
b <- c(3L, 4L, 5L, 6L)

union(a, b)

[1] 1 2 3 4 5 6

4.22 Union of n lists

a  <-  list(c(1L, 2L, 3L, 4L), c(3L, 4L, 5L, 6L), c(1L, 5L, 7L, 8L))
for(i in length(a)){
  if(i == 1 && length(a) > 1) {
    union_list <- union(a[[i]], a[[i + 1]])
  } else {
    union_list <- union(union_list,a[[i]])
  }
}
print(union_list)

[1] 1 2 3 4 5 6 7 8

4.23 Zero-pad a list from the left

max_length = 10
a  <-  c(1L, 2L, 3L, 4L)
print(c(rep(0, (max_length - length(a))), a))

[1] 0 0 0 0 0 0 1 2 3 4

4.24 Zero-pad a list from the right

max_length = 10
a  <-  c(1L, 2L, 3L, 4L)
print(c(a,rep(0, (max_length - length(a)))))

[1] 1 2 3 4 0 0 0 0 0 0