Basics 1 • R is a powerful statistical and graphical environment. • Free, open-source, C-based, object-oriented programming language maintained and supported by community developers. • Popular in scientific community. • Extendible thru user-developed packages. • • • • R is effective for data management. Handles calculations involving vectors, arrays, and matrices. Large collection of tools for data analysis. Powerful graphical capabilities. http://cran.r-project.org/ 2 Outline Installation of R - Windows R GUI Customizing R R Code Editors R Features R Objects R Data Structures • Vectors • Lists • Factors • Arrays • Matrices • Strings • Data frames 3 Installation of R - Windows http://cran.us.r-project.org/ 4 Installation of R - Windows 1 / 5 Installation of R - Windows 6 Installation of R - Windows ## 32-bit (i386) vs. 64-bit (x64) Only relevant with 64-bit versions of Windows # Advantages.. • Better for handling large data structures 32-bit <1GB object size 64-bit >1GB object size # Disadvantages.. • Less efficient for small data structures (store 8 bytes rather than 4 bytes) • Less external software is available for 64-bit versions (ex. ODBC drivers) • Some packages not compatible with 64-bit builds 7 Installation of R - Windows ## Functions/Packages/Libraries in R ## Functions.. # Compiled code (built-in or developed) to perform certain tasks ## Packages.. # Collections of R functions, data, and compiled code in a well-defined format. search() # Shows available packages currently loaded ## Libraries.. # The directory where packages are stored library() # Shows installed packages ## List of available packages in R http://cran.r-project.org/web/packages/available_packages_by_name.html 8 Installation of R - Windows # Packages we will be using from CRAN • RODBC ODBC database access • rgdal geospatial data abstraction • raster geospatial data analysis with rasters • rgeos spatial geometry with polygons Choose one that is close to you 9 Installation of R - Windows # Install the package RODBC install.packages('RODBC', dependencies=TRUE) # To list all available packages in library library() ## Homework: # Install the rgdal, raster, and rgeos packages. # To install multiple packages pkgs <- c('rgdal', 'raster', 'rgeos') install.packages(pkgs, dependencies=TRUE) 10 Installation of R - Windows ## Getting help in R help(package = RODBC) help(odbcConnect) # Help for package # Help for functions # or.. ?odbcConnect ??odbc # Help for functions # Search for functions with odbc ## Components of help files for functions # Usage # Arguments # Details # Value # Note # Author(s) # See Also # Examples Shows parameters of functions Describes parameters More details of parameters The output from function Miscellaneous information of functions The creator of the function Other similar functions to link to An example using functions with executable code 11 R GUI ## File.. # Source R code.. # New script.. # Open script.. # Display files.. # Load/Save Workspace.. # Load/Save History.. # Change dir... Open and run R script Open text editor within R and start a new script Open a saved script within R Shows browser with files in working directory Load/save current R workspace (.Rdata) Load/save current R commands Changes working directory [ same as: setwd("dirpath") ] ## Working directory.. setwd("C:/Rworkshop") getwd() ## Use forward slashes 12 Customizing R ##To customize R environment # There is a text file called Rprofile.site in the user home directory (C:/.../R/R-3.0.1/etc). # This file is used to initialize settings every time you open an R workspace. # Here, you can add a default working directory or add options.. # To modify this file, open in a text editor, such as Notepad or Wordpad. # Add a line anywhere in the file with setwd("working directory") # Example: setwd("C:\\1IW\\1Projects") ## To set options (settings).. options() options("digits") help(options) # look at current options # look at current options for digits # get help on option settings a <- 1234567891234.123456789 a # Display a options(scipen=6) # bias against scientific notation options(digits=20) # controls number of digits to print a # Display a again options("digits") options(digits=7) # Return back to default 13 Exercise 1 ## Exercise 1 # What is your current directory? This is the default directory. # Change the working directory to your Rworkshop folder. # Add options(scipen=6) to your Rprofile.site file. Note: You many need administrative privileges, depending on system. 14 R Code Editors # R Commander: A basic statistics graphical user interface (GUI) for R (John Fox) http://socserv.mcmaster.ca/jfox/Misc/Rcmdr/ # Rstudio: A free, open source, integrated development environment for R. http://www.rstudio.com/ # Tinn-R A free, open source editor/work processor for Windows operating system only http://nbcgib.uesc.br/lec/software/des/editores/tinn-r/en # Notepad ++ A free source code editor that supports several languages http://notepad-plus-plus.org/ # NpptoR Similar to R gui built-in editor, extends functionality of code passing from Notepad++ to R. http://sourceforge.net/projects/npptor/ 15 R Features ## R code is immediately executed, not compiled… and object-oriented # Math 1 + 1 5 * 20 10 == 100 4^2 sqrt(4) abs(-5) # # # # # # Addition Multiplication Logical 4 squares Square root Absolute # Get time or date Sys.time() Sys.Date() # Variable assignment (R objects) a <- 1 + 1 a = 1 + 1 assign("a", 1 + 1) # Print object to screen print(a) 16 R Objects ## Objects.. # store data elements # are members of different classes # you can use different methods (functions) to operate on them ## Example objects # variables, vectors, lists, arrays, matrices, data frames ## Common attributes of R objects # class # # # mode # typeof # # method - defines type of object, what properties it possesses, how it behaves, and how it relates to other types of objects (numeric, character, logical, list, factor, matrix, dataframe, etc...) - storage mode or type of object (numeric, character, logical, list, function, etc...) - typeof is an internal descriptor for R, similar to mode, although somewhat more specific (See example below). - a function associated with a particular type of object (ex. summary, print) # Link to discussion on objects http://cran.r-project.org/doc/manuals/r-release/R-lang.html#Introduction 17 R Objects ## Two types of R objects – S3 and S4 # S3 objects – classes and methods from beginning – informal methods # S4 objects – classes and methods developed later – more formal methods (spatial) ## Object names.. # Case sensitive # Consists of letters, numbers, and the dot or underline character # Can not contain spaces or dashes '-' or special characters # Can not start with a number or a dot followed by number # Can not be a reserved word (stored R object). ## Testing object types and modes myObject <- 1.2345 # Create object isS4(myObject) mode(myObject) typeof(myObject) class(myObject) is.character(myObject) is.vector(myObject) # # # # # # Test if object is S4 object Get mode Get type Get class Test if object is character Test if object is vector 18 R Objects ## Creating/Removing R objects in R workspace myObject <- 1 ls() ls(pattern="my") rm(myObject); ls() # # # # Create object Lists objects in R workspace Lists only objects with 'my' in name Removes object from R workspace ## Saving/Loading/Removing R objects in working directory myObject <- 1 save(myObject, file="mydata.Rda") list.files(getwd()) list.files(getwd(), pattern=".Rda") rm(myObject); ls() load("mydata.Rda"); ls() # Saves object to working directory # Lists files in working directory # Lists only files ending in *.Rda # Loads object back to R workspace file.remove("mydata.Rda") help(file.remove) # Removes object from working directory file.exists("mydata.Rda") # Checks if file exists Note: *.Rda, *.rda, or *.Rdata are all valid R data formats 19 R Data Types # character 'Name' (Factor) # Note: a string is a character variable with 1 or more characters myObject <- "1" is.character(myObject) mode(myObject) # integer whole numbers (ex. 1, 2, 3) myObject <- 1 is.integer(myObject) mode(myObject) typeof(myObject) myObject <- as.integer(myObject) is.integer(myObject) mode(myObject) typeof(myObject) # numeric # # # # # # # # Create object Check if object is integer Check mode Check typeof Create new object Check if object is integer Check mode Check typeof double precision number. Identical to double (ex. 1.2345) myObject <- 1.2345 is.numeric(myObject) is.double(myObject) mode(myObject) typeof(myObject) # logical TRUE/FALSE myObject <- TRUE is.logical(myObject) mode(myObject) 20 Exercise 2 2.1 Create an object named x and assign it the value 𝟖. 2.2 Create an object named a and assign it to the value pi. Display the value of a. 2.3 Create an object named b and assign it to the value "pi". 2.4 What are the modes of a and b? 2.5 Without using pi create an object e that has the value 𝝅 + 𝟏. 2.6 Save e to a file named pi.Rda in your working directory, then remove e from your R workspace, then check it is not in the R workspace. 2.7 Load e back to R workspace and check that it is there. 2.8 Remove all the objects you created and the file you stored e in. Is your workspace empty? 21 R Data Structures # vector group of single objects or elements (all elements must be the same mode) # factors vector of values that are limited to a fixed set of values (categories) # list group of objects called components (can be different modes and lengths) # array group of vectors with more than 1 dimension (all elements must be the same mode) format: array(data=NA, dim=c(dim1, dim2, ..) # matrix 2-dimensional array (group of vectors with rows and columns) (all elements must be the same mode). format: matrix(data=NA, nrow=1, ncol=1, byrow=FALSE) # data frame 2-dimensional list (group of vectors of the same length) (can be different modes) format: data.frame(row, col) Images from: https://www.stat.auckland.ac.nz/~paul/ItDT/HTML/node64.html 22 Vectors ## Vector - group of single objects or elements (all elements must be the same mode) a b d e f <<<<<- 1 + 1 5 * 20 a + b "string" TRUE # # # # # numeric numeric numeric character logical # c – combines elements to a vector.. all elements coerced to common type help(c) g <- c(a, b, d) g <- c(a=a, b=b, d=d) g mode(g) # # # # Numeric vector Create a named vector Display values of g Display mode of g h <- c(d, e, f) h mode(h) names(h) <- c("d","e","f") names(h) h # # # # # # Change all elements to character Display values of h Display mode of h Create a named vector Display the names of elements of h Display names and values of elements of h 23 Vectors ## Vector cont… print(g) g # Print g to console # Display contents of g ## Accessing elements of vector g[1] g[c(1,3)] g[1:3] g["b"] names(g)[2] g[c(1,"b")] g[c("a","b")] # # # # # # # Display first element of vector Display first and third element of vector Display first thru third elements of vector Display element named "b" Display the name of second element of vector Note: can not combine element number and name Correct way ## Add/Remove elements of a vector g["e"] <- 50 # g <- c(g, 60) # g # names(g)[5] names(g)[5] <- "last" # print(g) # Add element named 'e' to vector g Another way to add an element to vector Note: no name for last element Add name to last element of g Display g 24 Exercise 3 ## Run the code on the previous slides.. 3.1 Form a vector named j, consisting of the objects b, d and e, with names 'b', 'd' and 'e'. 3.2 What is the mode of j? Check whether j is a vector (Hint: use is.******( ) function). 3.3 Add the elements of vector g named "b" and "d". Do the same for the vector j. Why the error message for one and not the other? Change the mode of the elements in j to numeric and try again. 3.4 Replace the "d" element of the vector g with the sum of the elements "b" and "last" of the vector g. What is the value of the element "d" of the vector g? 3.5 Clean up your workspace, remove all objects. We would like to remove all the objects without typing them into rm(). Hint, try list=ls() and print the object list onto the screen. Can you combine this with rm()? You have to be careful with this, but it is a way clear your workspace up. 25 Vectors ## Generate vectors v1 v2 v3 v1 v4 <<<<<- seq(1,20) seq(1,40,2) rep(1, 20) sample(v1) v1 / v2 # # # # # Create vector of numbers from 1 to 20 Create vector of number 1 to 40 by 2 Create vector of 1 with length 20 Creates a permutation of v1 Create vector from other vectors # # # # # # Mean of vector Max value vector Order vector Number of elements in vector Sum elements of vector Round elements of vector by 2 decimal places mode(v1) mode(v4) typeof(v1) typeof(v4) ## Vector functions mean(v1) max(v1) sort(v1) length(v1) sum(v1) round(v4, 2) v5 <- sort(v1) # Makes new vector equal to v1 in order v5 v5 + 2 # Adds 2 to each element of v5 c(rep(-1,10), rep(2,10)) # Creates a vector of 20 elements v5 + c(rep(-1,10), rep(2,10)) # Adds the two vectors element by element 26 Vectors ## Logical operators >, >= <, <= ==, != x&y x|y %in% !x # greater than, greater than or equal to # less than, less than or equal to # equal to; not equal to # and # or # equal to a set of values # not ## Logical vectors are conditional statements v5; mode(v5) length(v5) == 10 length(v5) == 20 # Display v5; check mode # Is the number of elements of v5 equal to 10? # Is the number of elements of v5 equal to 20? is.character(v5) !is.character(v5) # Are elements of v5 character? # Are elements of v5 not character? v5 %in% c(100:200) v5 < 5 # Are the elements of v5 in the range 100 to 200? # Are the elements of v5 less than 5? all(v5 < 5) any(v5 < 5) which(v1 < 5) # # # # Do all element of v5 meet logical condition(<5)? Do any element of v5 meet logical condition(<5)? Position of elements from v1 which meet logical condition(<5). 27 Vectors ## Logical operators – Example # Find the mean of all elements in vect5 which are greater than 15. We can do it in steps. # Step 1: The logical vector for elements which are greater than 15 v5 > 15 # Step 2: The vector of elements in v5 which are greater than 15 v5[v5 > 15] temp.vect <- v5[v5 > 15] # Display on screen # Assign to an object # Step 3: The mean of all elements in v5 which are greater than 15 mean(v5[v5 > 15]) mean(temp.vect) # Display on screen # Use the assigned vector 28 Vectors ## Logical operators – More examples # Logical vectors v6 <- v5 + 10; v6 v6 < 13 v6[which(v6 < 13)] # Add 5 to v5 and assign to v6; Display v6 # Logical vector for condition (< 13) # Integer vector of elements of v6 which are < 13 # Vector elements v6[v6 < 13] v6[v6 < 13 | v6 > 25] v6[v6 == 20] v6[v6 != 20] v6[v6 %in% c(20:25)] v6[!v6 %in% c(20:25)] # # # # # # Vector Vector Vector Vector Vector Vector of of of of of of elements elements elements elements elements elements less than 13 less than 13 or greater than 25 equal to 20 not equal to 20 equal to values 20 thru 25 not equal to values 20 thru 25 # Functions to vector elements sum(v6 < 13) sum(v6[v6 < 13]) min(v6[v6 < 13]) # Number of elements less than 13 # Sum of elements less than 13 # Minimum value of elements less than 13 # Change vector elements based on logical vector v6[v6 >= 20] <- 10 sort(v6) # Change values > 20 to 10 # Display vector in order 29 Vectors ## Creating vectors from a sample ## We will see later that logical vectors are used a lot in R!! vect5 <- sample(1:30, 25, replace = TRUE) # Look at help(sample) length(vect5) vect5 # Run above code. Are your vector and my vector the same? vect6 <- sample(1:30,25,replace = TRUE) vect5 == vect6 # Is vect5 the same vector as vect6? sum(vect5 == vect6) # A way to make them the same no matter which computer run on set.seed(1234, kind=NULL); vect5 <- sample(1:30,25,replace = TRUE) vect5 # Does your vector and mine vector agree now? set.seed(1234, kind=NULL); vect6 <- sample(1:30,25,replace = TRUE) sum(vect5 == vect6) 30 Exercise 4 # Run the following code to create vect1 and vect2: vect1 <- c(rep(1,10), rep(2,10)) # Creates a vector named vect1, with length 20, where the first 10 elements are 1 and next 10 # elements are 2. vect2 <- c(seq(1,30), seq(40,60)) # Creates a vector named vect2, which contains the numbers from 1 to 30 and numbers from # 40 to 60. 4.1 Create a vector named vect3, which contains a sample of size 20, without replacement, from the numbers between 1 to 30 and from 40 to 50. Hint, use vect2 and the function sample(). So we can compare answers set a seed of 673. Display vect3. 4.2 Add 1 to the first 10 elements of vect3 and 2 to the next 10 elements. Hint use vect1. 4.3 How many elements in vect3 are greater than 25? 4.4 How many elements in vect3 are less than 50? 4.5 What is the max of the elements in vect3 which are less than 50? 4.6 How many elements in vect3 are greater than 25 and less than 50? 4.7 What is the mean of the elements in vect3 are greater than 25 and less than 50? 31 Lists ## Lists - group of objects (can be different modes) a b d e f g <<<<<<- 1 + 1 # numeric 5 * 20 # numeric a + b # numeric "string" # character TRUE # logical c(a, b, d); g <- c(a=a, b=b, d=d) # vector i <- list(d, e, f) i <- list(d=d, e=e, f=f) i$g <- g i names(i) # # # # # list – (can be different mode) named components of list append a vector to list display list get names of list ## Accessing elements of a list i[1] i[1:3] i[[1]] i[["d"]] i$d names(i$g) i[["g"]] i[["g"]][2] # # # # # Identifies first element of list Identifies first thru third element of list Identifies value of first element of list Identifies value of list element "d" Identifies value of list element "d" # Get names of list element "g" # Get value of list element "g" # Get second element of list element "g" unlist(i[1:3]) # Converts first thru third list elements to a vector unlist(i) # Converts list to a vector 32 Exercise 5 ## Run the code on the previous slides and then the following code. h <- c(d, e, f) names(h) <- c("d","e","f") 5.1 What is the mode of i ? What is the mode of h? 5.2 What is the mode of i[1]? What is the mode of i[[1]]? 5.3 Print i[[2]] and h[2] and then compare their modes. 5.4 Print i[[3]] and h[3] and then compare their modes. 33 Factors ## Factors – categorical data # A vector whose elements can take on one of a fixed set of values, called levels. # used in specific model and plotting function # requires less storage because each unique category is stored as a number ## Create a factor vector f <- factor(c("one", " two", "three")) mode(f) class(f) ## Accessing elements of factor f[1:2] levels(f) # Identifies first 2 elements of factor vector # Identifies different levels of factor vector ## Add elements to a factor f[4] <- "four" levels(f)[4] <- "four" f[4] <- "four" as.character(f) # # # # Add element to factor (error: invalid) Add new level to factor levels Add element to factor Converts factor vector to character vector 34 Arrays/Matrices # array # group of vectors with more than 1 dimension (all elements must be the same mode) # matrix # 2-dimensional array (a group of vectors with rows and columns, all of same mode). matrix(data=NA, nrow=1, ncol=1, byrow=FALSE, dimnames=NULL) array(data=NA, dim=c(dim1, dim2, ..) ## Array array(data=0, dim=c(5,2)) array(data=0, dim=c(5,2,4)) # 2-dimensional array (matrix) # 3-dimensional array ## Matrix g <- rep(1,3) h <- seq(3) i <- c("one", "two", "three") matrix(data=0, nrow=5, ncol=2) mat <- matrix(c(g, h), nrow=3, ncol=2) mat2 <- matrix(c(h, i), nrow=3, ncol=2) # # # # dimnames(mat) <- list(NULL, c("h", "i")) # rownames <- c("row1", "row2", "row3") # dimnames(mat) <- list(rownames, c("h", "i"))# Create matrix of 0 values Create matrix of 2 vectors, g and h Create matrix of 2 vectors, h and i (changes all values to strings) Name columns of matrix Create row names Name columns and rows of matrix matrix(c(1,2,3,4,5,6), ncol=2, nrow=3, byrow=FALSE) # fill matrix by column matrix(c(1,2,3,4,5,6), ncol=2, nrow=3, byrow=TRUE) # fill matrix by row 35 Matrices ## Matrix manipulation mat is.matrix(mat) dim(mat) t(mat) c(mat) c(t(mat)) # # # # # # Display matrix mat Check if object is a matrix Get dimensions of matrix transpose matrix Create a vector from matrix Create a vector from transposed matrix ## Accessing elements of a matrix mat[1,2] mat[3,2] mat[2,] mat[,2] mat[2:3,2] # # # # # Identify Identify Identify Identify Identify value in row 1, column 2 value in row 3, column 2 values in row 2 (vector) values in column 2 (vector) values in rows 2 thru 3 and column 2 (vector) mat[mat==1] <- 11 # Change all values of 1 to 11 ## Add/Remove elements of a matrix mat2 <- rbind(mat2, c("new", "row")) mat2 <- mat2[-(2:3),] # Add row to matrix # Removes 2nd thru 3rd row of matrix 36 Matrices ## Vector & Matrix calculations vect <- rep(5, 5) vect2 <- seq(1,3) mat1 <- matrix(data=c(rep(1,5), rep(2,5)), nrow=5, ncol=2) mat2 <- matrix(data=c(rep(5,5), rep(2,5)), nrow=5, ncol=2) # Element-wise vect + mat1 vect2 + mat1 vect * mat1 mat2 - 1 # # # # Add vect Elements Multiply Subtract elements to all elements of mat1 wise addition the vector just repeats vect elements to all elements of mat1 1 from all elements of mat2 vect * t(mat1) # Multiply vect with transposed matrix mat1 * mat2 t(mat1 * mat2) # Multiply all elements of mat1 with all elements of mat2 # Transpose results of multiplication # Product vect %*% mat1 # Product of vect multiplied by elements of mat1 37 Strings ## String functions str <- "filename.csv" # Define string nchar(str) # Get number of characters in string strsplit(str, "[.]") unlist(strsplit(str, "[.]")) unlist(strsplit(str, "\\.")) a <- unlist(strsplit(str, "[.]"))[1] b <- strsplit(str, "[.]")[[1]][2] # # # # # extension(str) # Get the extension of a string (raster) grep("file", str) sub("file", "new", str) # Find pattern in string # Substitute one pattern for new pattern toupper(str) # Convert string to upper case Get Get Get Get Get components of string split by . components of string split by . components of string split by . first component of string split second component of string split paste("one", "two", "three", sep="-")# Concatenate strings paste(a, "_2.", b, sep="") # Concatenate strings 38 Data Frames ## Data frames are the primary data structure in R. ## Data frames are used for storing data tables, such as forest inventory data tables. ## A data frame is similar structure to a matrix, except a data frame may contain categorical data, such as species names. ## Each column of a data frame is treated as a vector component of a list and therefore, can be different modes. The difference is that each vector component must have same length. 39 Data Frames # data frame # 2-dimensional list (group of vectors of the same length; can be different modes) data.frame(row, column) ## Start with a matrix mat <- matrix(data=c(seq(1,5), rep(2,5)), nrow=5, ncol=2) df <- data.frame(mat) is.data.frame(df) dim(df) str(df) matv <- c(mat) is.vector(matv) dflst <- c(df) is.list(dflst) # # # # # Convert matrix to data frame Check if object is a data frame Get dimensions of data frame Get structure of data frame Create a vector from matrix # Create a list from data frame ## Accessing elements of a data frame ## Data frames can be accessed exactly like matrices, but they can also be accessed by column names. df[3,1] df[3,] df[,2] df[2:4,1] # # # # Identify Identify Identify Identify value in row 3, column 1 values in row 3 (vector) values in column 2 (vector) values in rows 2 thru 4 and column 1 (vector) df[3,"X2"] df[,"X2"] df[2:4,"X1"] # Identify value in row 3, column 2 # Identify values in column 2('X2') # Identify values in rows 2 thru 4 and column 1('X1') 40 Data Frames ## Building your own data frame.. dat <- edit(data.frame()) ## Build data frame from vectors of rows and columns.. # Column vectors numbervect <- c(1, 2, 3) stringvect <- c("a", "b", "c") logicalvect <- c(TRUE, FALSE, TRUE) # Combine column vectors into a data frame and name columns df <- data.frame(cbind(numbervect, stringvect, logicalvect)) df <- data.frame(cbind(COLUMN1=numbervect, COLUMN2=stringvect, COLUMN3=logicalvect)) # Row vectors row1vect <- c(1, "a", TRUE) row2vect <- c(2, "b", FALSE) row3vect <- c(3, "c", TRUE) # Combine row vectors into a data frame df <- data.frame(row1vect, row2vect, row2vect) # Name data frame columns names(df) <- c("COLUMN1", "COLUMN2", "COLUMN3") 41 Exercise 6 Scenerio: You collected data on one plot today. We need to compile the data in R for analysis. There were 5 trees: pine, pine, walnut, walnut, alder The heights were: 100, 75, 120, 90, 50 The tree status was: live, live, live, dead, live 6.1 Create a vector with 5 elements of tree names and assign it to an object named 'tree'. 6.2 Display the number of elements in the tree vector? 6.3 What is the mode of the tree vector? 6.4 Display the .number of elements in the tree vector that are "walnut". 6.5 Create a vector with 5 elements of tree heights and assign it to an object named 'ht'. 6.6 What is the mode of the ht vector? 6.7 What is the maximum height of all 5 trees?.. what is the average height? 6.8 Create another vector of 5 elements with tree status and assign to an object named 'status'. 6.9 What is the mode of 'status'? 6.10 Change 'status' to a factor with 2 levels, 1:live; 2:dead and assign back to object 'status'. 42 Exercise 6 cont.. 6.11 Create a data frame object named 'treesdf', with the 3 vectors you just made, 'tree', 'ht', and 'status'. 6.12 What are the dimensions of treesdf? 6.13 What are the column names of treesdf? 6.14 What does the structure of treesdf look like? 6.15 You missed a tree. It was a dead pine tree with height of 30 meters. Add it to treesdf and assign this new data frame to on object named 'treesdf2'. 6.16 Save the object, treesdf2 to a file in your workspace named 'treesdf2.Rda'. 43 R Help Links # List of available packages in R http://cran.r-project.org/web/packages/available_packages_by_name.html http://www.cran.r-project.org/doc/manuals/R-intro.pdf # Link to discussion on objects http://cran.r-project.org/doc/manuals/r-release/R-lang.html#Introduction # Link to discussion on S4 classes and Methods http://www.r-project.org/conferences/useR-2004/Keynotes/Leisch.pdf # R Wiki - Tips http://rwiki.sciviews.org/doku.php?id=tips:tips#data 44 Basics 45