1 Introduction

A data set that have more than one dimension is conceptually hard to store as a vector. For two-dimensional data set the solution to this is to instead use matrices or data frames. As with vectors all values in a matrix has to be of the same type (eg. you can not mix for example characters and numerics in the same matrix). For data frames this is not a requirement and different columns can have different modes, but all columns in a data frame have the same number of entries. In addition to these R also have objects named lists that can store any type of data set and are not restricted by types or dimensions.

In this exercise you will learn how to:

  • Create and work with matrices, data frames and lists
  • Perform basic math operator on matrices
  • Use functions to summarize information from data frames
  • Extract subsets of data from matrices, data frames and lists
  • Create S3 object from a list

2 Matrices

The command to create a matrix in R is matrix(). As input it takes a vector of values, the number of rows and the number of columns.

X <- matrix(1:12, nrow = 4, ncol = 3)
X
##      [,1] [,2] [,3]
## [1,]    1    5    9
## [2,]    2    6   10
## [3,]    3    7   11
## [4,]    4    8   12

Note that if one only specify the number of rows or columns the it will infer the size of the matrix automatically using the size of vector and the option given. The default way of filling the matrix is column-wise, so the first values from the vector ends up in column 1 of the matrix. If you instead wants to fill the matrix row by row you can set the byrow flag to TRUE.

X <- matrix(1:12, nrow = 4, ncol = 3, byrow = TRUE)
X
##      [,1] [,2] [,3]
## [1,]    1    2    3
## [2,]    4    5    6
## [3,]    7    8    9
## [4,]   10   11   12

Subsetting a matrix is done the same way as for vectors, but you have more than one dimension to work with. So you specify the rows and column needed.

X[1,2]
## [1] 2

If one wants all values in a column or a row this can be specified by leaving the other dimension empty, hence this code will print all values in the second column.

X[,2]
## [1]  2  5  8 11

Note that if the retrieved part of a matrix can be represented as a vector (eg one of the dimension have the length 1) R will convert it to a vector otherwise it will still be a matrix.

2.1 Exercise

Create a matrix containing 1:12 as shown similar to the matrix X above.

  1. How do find out the length and the mode of the matrix?

mode(X)
length(X)
## [1] "numeric"
## [1] 12
  1. Extract all the values in the matrix that is larger than 6.

X[X>6]
## [1]  7 10  8 11  9 12
  1. Swap the positions of column 1 and 3 in the matrix X

X[,c(3,2,1)]
##      [,1] [,2] [,3]
## [1,]    3    2    1
## [2,]    6    5    4
## [3,]    9    8    7
## [4,]   12   11   10
  1. Add a vector with three zeros as a fifth row to the matrix

X.2 <- rbind(X, rep(0, 3))
X.2
##      [,1] [,2] [,3]
## [1,]    1    2    3
## [2,]    4    5    6
## [3,]    7    8    9
## [4,]   10   11   12
## [5,]    0    0    0
  1. Replace all values the first two columns in your matrix with NA.

X[,1:2] <- NA
X
##      [,1] [,2] [,3]
## [1,]   NA   NA    3
## [2,]   NA   NA    6
## [3,]   NA   NA    9
## [4,]   NA   NA   12
  1. Replace all values in the matrix with 0 and convert it to a vector

X[] <- 0
as.vector(X)
##  [1] 0 0 0 0 0 0 0 0 0 0 0 0
  1. In the the earlier exercises, you created a vector with the names of the type Geno_a_1, Geno_a_2, Geno_a_3, Geno_b_1, Geno_b_2…, Geno_s_3 using vectors. In today’s lecture, a function named outer() that generates matrices was mentioned. Try to generate the same vector as yesterday using this function instead. The outer() function is very powerful, but can be hard to wrap you head around, so try to follow the logic, perhaps by creating a simple example to start with.
letnum <- outer(paste("Geno",letters[1:19], sep = "_"), 1:3, paste, sep = "_")
class(letnum)
sort(as.vector(letnum))
## [1] "matrix" "array" 
##  [1] "Geno_a_1" "Geno_a_2" "Geno_a_3" "Geno_b_1" "Geno_b_2" "Geno_b_3"
##  [7] "Geno_c_1" "Geno_c_2" "Geno_c_3" "Geno_d_1" "Geno_d_2" "Geno_d_3"
## [13] "Geno_e_1" "Geno_e_2" "Geno_e_3" "Geno_f_1" "Geno_f_2" "Geno_f_3"
## [19] "Geno_g_1" "Geno_g_2" "Geno_g_3" "Geno_h_1" "Geno_h_2" "Geno_h_3"
## [25] "Geno_i_1" "Geno_i_2" "Geno_i_3" "Geno_j_1" "Geno_j_2" "Geno_j_3"
## [31] "Geno_k_1" "Geno_k_2" "Geno_k_3" "Geno_l_1" "Geno_l_2" "Geno_l_3"
## [37] "Geno_m_1" "Geno_m_2" "Geno_m_3" "Geno_n_1" "Geno_n_2" "Geno_n_3"
## [43] "Geno_o_1" "Geno_o_2" "Geno_o_3" "Geno_p_1" "Geno_p_2" "Geno_p_3"
## [49] "Geno_q_1" "Geno_q_2" "Geno_q_3" "Geno_r_1" "Geno_r_2" "Geno_r_3"
## [55] "Geno_s_1" "Geno_s_2" "Geno_s_3"
  1. Create two different 2 by 2 matrices named A and B. A should contain the values 1-4 and B the values 5-8. Try out the following commands and by looking at the results see if you can figure out what is going on.
A. A * B
B. A / B
C. A %x% B
D. A + B
E. A - B
F. A == B

A <- matrix(1:4, ncol = 2, nrow = 2)
B <- matrix(5:8, ncol = 2, nrow = 2)
A
B

A * B
A / B
A %x% B
A + B
A - B
A == B
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
##      [,1] [,2]
## [1,]    5    7
## [2,]    6    8
##      [,1] [,2]
## [1,]    5   21
## [2,]   12   32
##           [,1]      [,2]
## [1,] 0.2000000 0.4285714
## [2,] 0.3333333 0.5000000
##      [,1] [,2] [,3] [,4]
## [1,]    5    7   15   21
## [2,]    6    8   18   24
## [3,]   10   14   20   28
## [4,]   12   16   24   32
##      [,1] [,2]
## [1,]    6   10
## [2,]    8   12
##      [,1] [,2]
## [1,]   -4   -4
## [2,]   -4   -4
##       [,1]  [,2]
## [1,] FALSE FALSE
## [2,] FALSE FALSE
  1. Generate a 10 by 10 matrix with random numbers. Add row and column names and calculate mean and median over rows and save these in a new matrix.

e <- rnorm(n = 100)
E <- matrix(e, nrow = 10, ncol = 10)
colnames(E) <- LETTERS[1:10]
rownames(E) <- colnames(E)
E.means <- rowMeans(E)
E.medians <- apply(E, MARGIN = 1, median)
E.mm <- rbind(E.means, E.medians)
E.mm
##                     A          B         C         D          E         F
## E.means    0.07223155 -0.4384797 0.9333803 0.4141236 -0.8173714 0.1077078
## E.medians -0.25218486 -0.3921367 0.8865260 0.4181315 -0.9268971 0.1992055
##                    G          H           I          J
## E.means   -0.1955585 -0.1431702 -0.10769994 -0.1339876
## E.medians  0.1319904 -0.2499001 -0.02553699 -0.5363202

3 Dataframes

Even though vectors are at the very base of R usage, data frames are central to R as the most common ways to import data into R (read.table()) will create a dataframe. Even though a dataframe can itself contain another dataframe, by far the most common dataframes consists of a set of equally long vectors. As dataframes can contain several different data types the command str() is very useful to run on dataframes.

vector1 <- 1:10
vector2 <- letters[1:10]
vector3 <- rnorm(10, sd = 10)
dfr <- data.frame(vector1, vector2, vector3)
str(dfr)
## 'data.frame':    10 obs. of  3 variables:
##  $ vector1: int  1 2 3 4 5 6 7 8 9 10
##  $ vector2: chr  "a" "b" "c" "d" ...
##  $ vector3: num  -6.635 -6.512 2.82 -0.126 -4.164 ...

In the above example, we can see that the dataframe dfr contains 10 observations for three variables that all have different modes, column 1 is an integer vector, column 2 a vector with factors and column 3 a numeric vector. It is noteworthy that the second column is a factor even though we just gave it a character vector.

3.1 Exercise

  1. Figure out what is going on with the second column in dfr dataframe described above and modify the creation of the dataframe so that the second column is stored as a character vector rather than a factor. Hint: Check the help for data.frame to find an argument that turns off the factor conversion.

dfr <- data.frame(vector1, vector2, vector3, stringsAsFactors = FALSE)
str(dfr)
## 'data.frame':    10 obs. of  3 variables:
##  $ vector1: int  1 2 3 4 5 6 7 8 9 10
##  $ vector2: chr  "a" "b" "c" "d" ...
##  $ vector3: num  -6.635 -6.512 2.82 -0.126 -4.164 ...
  1. One can select columns from a data frame using either the name or the position. Use both methods to print the last two columns from the dfr data frame.

dfr[,2:3]
dfr[,c("vector2", "vector3")]
##    vector2     vector3
## 1        a  -6.6349169
## 2        b  -6.5121327
## 3        c   2.8201212
## 4        d  -0.1258961
## 5        e  -4.1641686
## 6        f   3.7659326
## 7        g -12.5828905
## 8        h   6.2856298
## 9        i -11.4270561
## 10       j  -5.5782424
##    vector2     vector3
## 1        a  -6.6349169
## 2        b  -6.5121327
## 3        c   2.8201212
## 4        d  -0.1258961
## 5        e  -4.1641686
## 6        f   3.7659326
## 7        g -12.5828905
## 8        h   6.2856298
## 9        i -11.4270561
## 10       j  -5.5782424
  1. Print all letters in the vector2 column of the data frame where the vector3 column has a positive value.

dfr[dfr$vector3>0,2]
dfr$vector2[dfr$vector3>0]
## [1] "c" "f" "h"
## [1] "c" "f" "h"
  1. Create a new vector combining the all columns of dfr separated by a underscore.

paste(dfr$vector1, dfr$vector2, dfr$vector3, sep = "_")
##  [1] "1_a_-6.63491690520662"  "2_b_-6.51213265670369"  "3_c_2.82012116134843"  
##  [4] "4_d_-0.125896075536032" "5_e_-4.16416861589904"  "6_f_3.76593260831026"  
##  [7] "7_g_-12.582890490632"   "8_h_6.2856298090718"    "9_i_-11.4270561398031" 
## [10] "10_j_-5.57824244218033"
  1. There is a dataframe of car information that comes with the base installation of R. Have a look at this data by typing mtcars. How many rows and columns does it have?

dim(mtcars)
ncol(mtcars)
nrow(mtcars)
## [1] 32 11
## [1] 11
## [1] 32
  1. Re-arrange the row names of this dataframe and save as a vector.

car.names <- sample(row.names(mtcars))
  1. Create a dataframe containing the vector from the previous question and two vectors with random numbers named random1 and random2.

random1 <- rnorm(length(car.names))
random2 <- rnorm(length(car.names))
mtcars2 <- data.frame(car.names, random1, random2)
mtcars2
##              car.names     random1     random2
## 1       Toyota Corolla  0.32749593  0.11780740
## 2            Merc 240D -0.47324424  0.23621054
## 3          AMC Javelin  0.51623412 -0.21682243
## 4           Merc 450SE  0.43313886 -0.02168139
## 5    Chrysler Imperial  0.29277631  0.57188479
## 6            Merc 280C -0.96153544 -0.63826796
## 7     Pontiac Firebird  0.84193356 -2.41545995
## 8            Mazda RX4 -0.58527782  1.21006677
## 9        Mazda RX4 Wag -1.16179433 -0.80006363
## 10      Ford Pantera L -0.13801278 -1.39753178
## 11            Fiat 128  1.79161210  1.14753189
## 12          Volvo 142E  0.60601647 -0.75798885
## 13        Ferrari Dino -2.88037962 -0.18466064
## 14       Porsche 914-2  0.92784889  0.51334919
## 15      Hornet 4 Drive -1.18186988 -1.13098329
## 16       Maserati Bora -0.44679422  0.87391525
## 17          Camaro Z28  0.90626331  0.30689101
## 18  Cadillac Fleetwood  0.33423781  0.35356091
## 19         Merc 450SLC  0.62419261 -1.85374166
## 20         Honda Civic  1.52961574  1.70934918
## 21        Lotus Europa -1.28032795  0.10420884
## 22           Fiat X1-9 -1.31027754  0.30562407
## 23            Merc 230 -0.08761560  0.65271099
## 24 Lincoln Continental -0.62886428  0.98698823
## 25          Datsun 710  1.10224456 -0.80493907
## 26             Valiant  0.03749382  1.18751251
## 27            Merc 280 -1.24388146 -1.29280276
## 28          Duster 360  1.96683169 -0.60886180
## 29          Merc 450SL  0.40945687  0.96750660
## 30    Dodge Challenger -0.27686555 -3.37422494
## 31   Hornet Sportabout -1.42758270  1.09628669
## 32       Toyota Corona  1.11700518 -0.44909936
  1. Now you have two dataframes that both contains information on a set of cars. A collaborator asks you to create a new dataframe with all this information combined. Create a merged dataframe ensuring that rows match correctly.

mt.merged <- merge(mtcars, mtcars2, by.x = "row.names", by.y = "car.names")
mt.merged
##              Row.names  mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## 1          AMC Javelin 15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
## 2   Cadillac Fleetwood 10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
## 3           Camaro Z28 13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
## 4    Chrysler Imperial 14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
## 5           Datsun 710 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## 6     Dodge Challenger 15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
## 7           Duster 360 14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
## 8         Ferrari Dino 19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
## 9             Fiat 128 32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
## 10           Fiat X1-9 27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
## 11      Ford Pantera L 15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
## 12         Honda Civic 30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## 13      Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
## 14   Hornet Sportabout 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
## 15 Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
## 16        Lotus Europa 30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
## 17       Maserati Bora 15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
## 18           Mazda RX4 21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## 19       Mazda RX4 Wag 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## 20            Merc 230 22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## 21           Merc 240D 24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## 22            Merc 280 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
## 23           Merc 280C 17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
## 24          Merc 450SE 16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
## 25          Merc 450SL 17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
## 26         Merc 450SLC 15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
## 27    Pontiac Firebird 19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
## 28       Porsche 914-2 26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
## 29      Toyota Corolla 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
## 30       Toyota Corona 21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
## 31             Valiant 18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
## 32          Volvo 142E 21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
##        random1     random2
## 1   0.51623412 -0.21682243
## 2   0.33423781  0.35356091
## 3   0.90626331  0.30689101
## 4   0.29277631  0.57188479
## 5   1.10224456 -0.80493907
## 6  -0.27686555 -3.37422494
## 7   1.96683169 -0.60886180
## 8  -2.88037962 -0.18466064
## 9   1.79161210  1.14753189
## 10 -1.31027754  0.30562407
## 11 -0.13801278 -1.39753178
## 12  1.52961574  1.70934918
## 13 -1.18186988 -1.13098329
## 14 -1.42758270  1.09628669
## 15 -0.62886428  0.98698823
## 16 -1.28032795  0.10420884
## 17 -0.44679422  0.87391525
## 18 -0.58527782  1.21006677
## 19 -1.16179433 -0.80006363
## 20 -0.08761560  0.65271099
## 21 -0.47324424  0.23621054
## 22 -1.24388146 -1.29280276
## 23 -0.96153544 -0.63826796
## 24  0.43313886 -0.02168139
## 25  0.40945687  0.96750660
## 26  0.62419261 -1.85374166
## 27  0.84193356 -2.41545995
## 28  0.92784889  0.51334919
## 29  0.32749593  0.11780740
## 30  1.11700518 -0.44909936
## 31  0.03749382  1.18751251
## 32  0.60601647 -0.75798885
  1. Calculate the mean value for the two columns that you added to the mtcars data frame. Check out the function colMeans().

colMeans(mtcars2[, c("random1", "random2")])
##      random1      random2 
## -0.009997674 -0.112678896

Try to modify so you get the mean by cylinder instead. Check out the function aggregate().

aggregate(mtcars2$random1, by=list(mtcars$cyl), FUN=mean)
##   Group.1          x
## 1       4  0.1685754
## 2       6  0.1003698
## 3       8 -0.2054888

4 Lists

The last data structure that we will explore are lists, which is a very flexible structure. Lists can combine different data structures and they do not have to be of equal dimensions or have other restrictions. The drawback with a flexible structure is that it requires a bit more work to interact with.

The syntax to create a list is similar to creation of the other data structures in R.

l <- list(1, 2, 3)

As with the data frames the str() command is very useful for the sometimes fairly complex lists instances.

str(l)
## List of 3
##  $ : num 1
##  $ : num 2
##  $ : num 3

This example containing only numeric vector is not very exciting example given the flexibility a list structure offers so let’s create a more complex example.

vec1 <- letters
vec2 <- 1:4
mat1 <- matrix(1:100, nrow = 5)
df1 <- as.data.frame(cbind(10:1, 91:100))
u.2 <- list(vec1, vec2, mat1, df1, l)

As you can see a list can not only contain other data structures, but can also contain other lists.

Looking at the str() command reveals much of the details of a list

str(u.2)
## List of 5
##  $ : chr [1:26] "a" "b" "c" "d" ...
##  $ : int [1:4] 1 2 3 4
##  $ : int [1:5, 1:20] 1 2 3 4 5 6 7 8 9 10 ...
##  $ :'data.frame':    10 obs. of  2 variables:
##   ..$ V1: int [1:10] 10 9 8 7 6 5 4 3 2 1
##   ..$ V2: int [1:10] 91 92 93 94 95 96 97 98 99 100
##  $ :List of 3
##   ..$ : num 1
##   ..$ : num 2
##   ..$ : num 3

With this more complex object, subsetting is slightly trickier than with more the more homogenous objects we have looked at so far.

To look at the first entry of a list one can use the same syntax as for the simpler structures, but note that this will give you a list of length 1 irrespective of the actual type of data structure found.

u.2[1]
str(u.2[1])
## [[1]]
##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
## [20] "t" "u" "v" "w" "x" "y" "z"
## 
## List of 1
##  $ : chr [1:26] "a" "b" "c" "d" ...

If one instead wants to extract the list entry as the structure that is stored, one needs to “dig” deeper in the object.

u.2[[1]]
str(u.2[[1]])
##  [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
## [20] "t" "u" "v" "w" "x" "y" "z"
##  chr [1:26] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" ...

This means that the syntax to extract a specific value from a data structure stored in a list can be daunting. Below we extract the second column of a dataframe stored at position 4 in the list u.2.

u.2[[4]][,2]
##  [1]  91  92  93  94  95  96  97  98  99 100

4.1 Exercise

  1. Create a list containing 1 character vector, a numeric vector, a character matrix.

list.2 <- list(vec1 = c("hi", "ho", "merry", "christmas"),
               vec2 = 4:19,
               mat1 = matrix(as.character(100:81),nrow = 4))
list.2
## $vec1
## [1] "hi"        "ho"        "merry"     "christmas"
## 
## $vec2
##  [1]  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19
## 
## $mat1
##      [,1]  [,2] [,3] [,4] [,5]
## [1,] "100" "96" "92" "88" "84"
## [2,] "99"  "95" "91" "87" "83"
## [3,] "98"  "94" "90" "86" "82"
## [4,] "97"  "93" "89" "85" "81"
  1. Here is a dataframe.
dfr <- data.frame(letters, LETTERS, letters == LETTERS)

Add this dataframe to the list created above.

list.2[[4]] <- dfr
  1. Remove the the second entry in your list.

list.2[-2]
## $vec1
## [1] "hi"        "ho"        "merry"     "christmas"
## 
## $mat1
##      [,1]  [,2] [,3] [,4] [,5]
## [1,] "100" "96" "92" "88" "84"
## [2,] "99"  "95" "91" "87" "83"
## [3,] "98"  "94" "90" "86" "82"
## [4,] "97"  "93" "89" "85" "81"
## 
## [[3]]
##    letters LETTERS letters....LETTERS
## 1        a       A              FALSE
## 2        b       B              FALSE
## 3        c       C              FALSE
## 4        d       D              FALSE
## 5        e       E              FALSE
## 6        f       F              FALSE
## 7        g       G              FALSE
## 8        h       H              FALSE
## 9        i       I              FALSE
## 10       j       J              FALSE
## 11       k       K              FALSE
## 12       l       L              FALSE
## 13       m       M              FALSE
## 14       n       N              FALSE
## 15       o       O              FALSE
## 16       p       P              FALSE
## 17       q       Q              FALSE
## 18       r       R              FALSE
## 19       s       S              FALSE
## 20       t       T              FALSE
## 21       u       U              FALSE
## 22       v       V              FALSE
## 23       w       W              FALSE
## 24       x       X              FALSE
## 25       y       Y              FALSE
## 26       z       Z              FALSE
  1. Create a new list that contain 20 sublists, with each entry holding a numeric vector.

vec1 <- rnorm(1000)
list.a <- split(vec1, 1:20)
  1. How long is your list, and how long are each of the vectors that are part of the list?

length(list.a)
lapply(list.a, FUN = "length")
## [1] 20
## $`1`
## [1] 50
## 
## $`2`
## [1] 50
## 
## $`3`
## [1] 50
## 
## $`4`
## [1] 50
## 
## $`5`
## [1] 50
## 
## $`6`
## [1] 50
## 
## $`7`
## [1] 50
## 
## $`8`
## [1] 50
## 
## $`9`
## [1] 50
## 
## $`10`
## [1] 50
## 
## $`11`
## [1] 50
## 
## $`12`
## [1] 50
## 
## $`13`
## [1] 50
## 
## $`14`
## [1] 50
## 
## $`15`
## [1] 50
## 
## $`16`
## [1] 50
## 
## $`17`
## [1] 50
## 
## $`18`
## [1] 50
## 
## $`19`
## [1] 50
## 
## $`20`
## [1] 50
  1. Figure out what the main differences are between the function lapply() and sapply are and use both of them with the function summary on your newly created list. What are the pros and cons of the two approaches to calculate the same summary statistics?

lapply(X = list.a, FUN = "summary")
sapply(X = list.a, FUN = "summary")
## $`1`
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -2.36469 -0.91051 -0.03343 -0.07989  0.48084  3.11180 
## 
## $`2`
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -1.347246 -0.739802  0.009077 -0.002178  0.657415  2.165015 
## 
## $`3`
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -1.3995 -0.3672  0.2293  0.1976  0.7565  2.0539 
## 
## $`4`
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -2.7741 -0.7620 -0.2279 -0.2466  0.4847  2.0523 
## 
## $`5`
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -1.83020 -0.66702 -0.10963 -0.02304  0.63560  2.92258 
## 
## $`6`
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -1.6584 -0.8681  0.1233  0.1058  0.8156  2.4574 
## 
## $`7`
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -1.68019 -0.05437  0.48908  0.41887  0.94105  2.45776 
## 
## $`8`
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -2.5917 -0.5402  0.4116  0.1850  1.0308  1.9770 
## 
## $`9`
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -2.18075 -0.76067  0.03677 -0.06255  0.71313  1.77039 
## 
## $`10`
##       Min.    1st Qu.     Median       Mean    3rd Qu.       Max. 
## -2.2164261 -0.6163273 -0.1229226 -0.0000073  0.5190551  2.4082552 
## 
## $`11`
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -1.7927 -0.4465  0.1742  0.2239  0.9305  3.1301 
## 
## $`12`
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -1.85222 -0.48885  0.05057  0.12685  0.79729  2.21231 
## 
## $`13`
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -2.6039 -0.8113 -0.1601 -0.1587  0.5977  2.2487 
## 
## $`14`
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -2.3097 -0.6573 -0.1373 -0.1652  0.3516  2.0582 
## 
## $`15`
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -1.9483 -1.0082 -0.1180 -0.1711  0.3774  1.7604 
## 
## $`16`
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
## -2.2521 -0.9970 -0.2452 -0.1250  0.7058  2.4589 
## 
## $`17`
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -2.679814 -0.871988  0.077710 -0.002874  0.694424  2.471863 
## 
## $`18`
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -1.76092 -0.48491  0.01564  0.15995  1.12870  2.06540 
## 
## $`19`
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -2.99094 -0.77520  0.02274 -0.20609  0.60228  1.42447 
## 
## $`20`
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
## -1.95360 -0.42358  0.08091  0.04319  0.82220  1.35410 
## 
##                   1            2          3          4           5          6
## Min.    -2.36468966 -1.347245507 -1.3994780 -2.7740698 -1.83019938 -1.6583708
## 1st Qu. -0.91051350 -0.739801958 -0.3671521 -0.7620060 -0.66702157 -0.8681190
## Median  -0.03343010  0.009077279  0.2293074 -0.2279210 -0.10963317  0.1233247
## Mean    -0.07988735 -0.002177729  0.1975780 -0.2466108 -0.02304394  0.1057883
## 3rd Qu.  0.48084338  0.657415072  0.7564576  0.4846886  0.63560119  0.8155753
## Max.     3.11179980  2.165015440  2.0539422  2.0523341  2.92258218  2.4574325
##                   7          8           9            10         11          12
## Min.    -1.68019311 -2.5917482 -2.18074968 -2.216426e+00 -1.7926548 -1.85222286
## 1st Qu. -0.05437249 -0.5401963 -0.76067324 -6.163273e-01 -0.4465496 -0.48884914
## Median   0.48908097  0.4116070  0.03677231 -1.229226e-01  0.1742192  0.05056518
## Mean     0.41886866  0.1850475 -0.06255328 -7.274891e-06  0.2238536  0.12684825
## 3rd Qu.  0.94105291  1.0307515  0.71312920  5.190551e-01  0.9304958  0.79729411
## Max.     2.45776135  1.9769727  1.77038923  2.408255e+00  3.1300681  2.21231324
##                 13         14         15         16           17          18
## Min.    -2.6039127 -2.3096729 -1.9483456 -2.2521299 -2.679814353 -1.76092393
## 1st Qu. -0.8113244 -0.6572605 -1.0081857 -0.9969751 -0.871987916 -0.48491172
## Median  -0.1600900 -0.1372973 -0.1180169 -0.2451834  0.077710313  0.01564432
## Mean    -0.1586731 -0.1652416 -0.1710685 -0.1249618 -0.002873922  0.15995350
## 3rd Qu.  0.5976524  0.3515691  0.3773515  0.7058406  0.694423837  1.12869994
## Max.     2.2487240  2.0581731  1.7603503  2.4589273  2.471862812  2.06539582
##                  19          20
## Min.    -2.99094319 -1.95359567
## 1st Qu. -0.77520229 -0.42358147
## Median   0.02274174  0.08091181
## Mean    -0.20608574  0.04319284
## 3rd Qu.  0.60227792  0.82220265
## Max.     1.42447116  1.35409502

5 Extras

  1. Design a S3 class that should hold information on human proteins. The data needed for each protein is:
  • The gene that encodes it
  • The molecular weight of the protein
  • The length of the protein sequence
  • Information on who and when it was discovered
  • Protein assay data

Create this hypothetical S3 object in R.

  1. Among the test data sets that are part of base R, there is one called iris. It contains measurements on set of plants. You can access the data using by typing iris in R. Explore this data set and calculate some useful summary statistics, like SD, mean and median for the parts of the data where this makes sense. Calculate the same statistics for any grouping that you can find in the data.