This scritpt is meant to demonstrate quickly the very first steps in R and basic commands used in the lecture series. It is not meant to be comprehensive. We will only use a small subset of the vast R ecosystem in the lectures. This script will be enough help to get you started and hopefully leave out unnecessary baggage.

Here is how to use this Introduction: Work in parallel in your own RStudio Environment. You can copy single lines of the code from this document into your “Console” windows and observe what happens. At the same time, also check the changes in the “Environment” window (right hand side) - which is where variables should show up (their names and some information).

If or when you feel ready to explore some more, you can check out details about the commands you learnt. You can obtain help and more information on how a command works by preceeding it with a question mark, like this

?sum

A page with more information on the function sum() should have shown up somewhere within your RStudio-Environment.

Now, let’s start!

First steps: Use R as calculator

Find the “Console” in your RStudio environment. This is the (inter)active place of your environment. You can use it as basic calculator. Try it!

Basic calculus: \(1+1= ?\)

(cut and past the folliwng line into the console, hit enter and see what happens)

1+1 
## [1] 2

The console hopefully returned the proper result after hitting enter, which is 2. Correct?

Let us prpceed in the same way with some other types of mathematical operations.

Power: \(2^3 = ?\)

2^3
## [1] 8

I hope the proper result showed up, which is 8. Below I will not further comment on the results you will optain when pasting the nest lines. But please proceed in the same way slowly, line by line, and observe closely whether the obtained result makes sense for you.

Many more operations are implemented in R, e.g. the log, sine or cosine, e.g.: $log(2) = $

log(2)  
## [1] 0.6931472

Note: log() yields the natural log while log10() yields the “common” logarithm (the log to the base 10).

Introduce variables

Calculations is great, but most of the time you want to implement formulas and store the result in a variable. Even is the most basic appliactions, this makes life not only convienient but most importanlt improves readibility of a script! Do use variables as much as you can. It will save time in the end.

Here is how to do it.

Define a variable by assigning it a value, e.g. \(a=2\)

a <- 2

You notice that the console remains quiet for once. Instead on the top right window “Environment”, “a” is now listed as variable (left column) and its value is shown in the right column. You can now work with the variable “a”, and we will do this in a minute. Before this, I need to take you on a very short detour about assigning variables in R.

  1. There is a second options to assign varaibles, which is this:
a1 = 2

In this particular case, and in most cases you will deal with, this yields the same result.

Introducing the difference between <- and = at the beginning of learning to program is overwhelming. I invite you to check this out at the end of the lecture series. For now, just so much: “=” will work, but be warned that many R-cracks think that <- is the right way to assign a variable. So if you want to get into a good habits from the start, use <-.

  1. Please be aware that variable names cannot start with a number. e.g. while a1<-2 is ok, the other way around is not: 1a <- 2 gives an error. Variable names should also not include “umlaute”.

Variable a is now ready to be used for any calculation you like, e.g.

b <- a^3

This creates the new variable b, showing up in the Environment Window, and it also has a value (hopefully the right one?). You can also obtain the value of b by typing in the Console

b
## [1] 8

and this returns in the next line the value of b, which is hopefully 8.

Variables can have many different types. We are not limited to single numbers, but can add more to form so called “arrays”, which can have one, two and more dimensions. To do this use the function “c()”, which “combines” several values. For example, let us create an array called height for tree height and one called DBH for the tree diameter at breast height:

height <- c(35, 37, 32, 33, 31, 29, 27, 26, 25, 23, 24) # tree height
DBH <- c(0.61,0.61,0.54,0.54,0.48,0.47,0.44,0.43,0.39,0.39) # tree diameter at breast height

Not only numbers can be combined, arrays can also contain text:

Species <- c("Beech", "Beech", "Oak", "Beech", "Oak","Beech", "Beech", "Oak", "Beech", "Oak")   

Also here, in order to view values of the variables in the console you can do two things: (a) Type the variable name at the prompt and hit

Species
##  [1] "Beech" "Beech" "Oak"   "Beech" "Oak"   "Beech" "Beech" "Oak"   "Beech"
## [10] "Oak"
  1. In scripts (see below) use parenthesis around the variable:
(Species)
##  [1] "Beech" "Beech" "Oak"   "Beech" "Oak"   "Beech" "Beech" "Oak"   "Beech"
## [10] "Oak"

So there are many options how a variable can look like, how many dimensions it has how many entries there are in each dimension, etc. Therefore, a number of functions allow to obtain information about properties of a variable. For example, find out how long an array is with

length(height)  # Returns the length of that array
## [1] 11

You can also place this information into a new variable (you may need it!)

l<-length(height)
l
## [1] 11

Another command allows obtaining an overview of a variable, e.g. its structure, including the data type and dimensions

str(Species)    
##  chr [1:10] "Beech" "Beech" "Oak" "Beech" "Oak" "Beech" "Beech" "Oak" ...

See if you can make sense of the result, more explantions follows in a minute.

Also, there are functions that perform mathematical operations now over theentire array. For exampole, the very handy function mean() calculates the arithmetic mean of an array quickly:

mean(height)     
## [1] 29.27273

Note: This only works, if all entries of the array have to be numeric entry. This is because the arithmetic mean cannot be calculated for e.g. text entries.

Thus, note that variables in R have several important properties that you often want to keep track off when working with them:

  • dimension (i.e. number of rows and columns)

  • structure (matrix, scalar, dataframe (similar to a data table, see below), lists, and many, many more!)

  • type (i.e. integer (German: “ganzzahlig”), numeric (decimal number), character (text), logical (TRUE / FALSE))

In the window “Environment” some of these properties are shown, i.e. the variable height is followed by the indication “num [1:11]”, which means that this variable is made up of several elements (11 to be precise) which are of the type “numerical”, which means a decimal number.

R figured this out automatically, a nice feature of this interpreted language. But by careful, R sometimes gets confused, when variables are not clearly defined by the user. A typical problem is confusion about the type. Types can be switched with a command of the general kind as.NEWTYPE. For example, assume you want to switch the type of the array height from numerical to character, use

height = as.character(height)
str(height)
##  chr [1:11] "35" "37" "32" "33" "31" "29" "27" "26" "25" "23" "24"

It worked, but we need the array later as a number, so let us switch it back again:

height = as.numeric(height)
str(height)
##  num [1:11] 35 37 32 33 31 29 27 26 25 23 ...

Multidimensional variables

We will work with data samples and therefore with multidimensional arrays (you can think of them like an excel table for two demensiona, but in R they can have even more dimensions). In order to work with them, you need some tools. Here they come.

Accessing specified elements of an array with “[ ]”:

Access the array at one specific index

(height)  # this shows the entire array
##  [1] 35 37 32 33 31 29 27 26 25 23 24
height[2] # this returns only the second element    
## [1] 37

Acess the array at several indices:

height[c(2,3)]   # returns the second and third element
## [1] 37 32

Note, how those indices are themselves in an array, which is c(2,3)

Acess the array at several indices 1 to 3 (e.g. 1,2 and 3):

height[1:3]  # returns elements 1 to 3
## [1] 35 37 32

Similarly, you can change specific elements of an array

height
##  [1] 35 37 32 33 31 29 27 26 25 23 24
height[2] <- 31 
height
##  [1] 35 31 32 33 31 29 27 26 25 23 24

To delete elements use negative indices, i.e. remove the 11-th element in “height”

str(height)
##  num [1:11] 35 31 32 33 31 29 27 26 25 23 ...
height=height[-11] 
str(height)
##  num [1:10] 35 31 32 33 31 29 27 26 25 23

Finally, you can also search through an array and find at which indices a specific condition is met using the function which() where in paranthesis the condition is given. For example, find out at which indices the height is larger than 30 m

which(height>30)
## [1] 1 2 3 4 5

You can store the output of the function, and use it later to access those indices, for example

(height) # just to display, so you see what we do
##  [1] 35 31 32 33 31 29 27 26 25 23
(DBH) # just to display, so you see what we do
##  [1] 0.61 0.61 0.54 0.54 0.48 0.47 0.44 0.43 0.39 0.39
i=which(height>30) # this is the operation 
DBH[i] # and here is an example how to use it, e.g., to check what is the diameter at breast hight of those taller trees.
## [1] 0.61 0.61 0.54 0.54 0.48

This is a very handy way of filtering data.

Note the important difference between “( )” and “[ ]”. Round parenthesis “( )” are associated with functions. The parenthesis behind the function, e.g. like mean(), contain the arguments handed to the function, e.g. mean(height). The squared parenthesis are soleyly used to address the indices in arrays, matrices, lists or data frames (e.g. multidimensional structures containing data).

Assigning values to or initializing arrays and matrices

It is often necessary to assign values to several elements at a time. Here are some common options to do this.

  1. Assign an increasing sequence with step size 1
x <- 1:20   
x   
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
  1. Assign a decreasing sequence
y <- 20:1   
y   
##  [1] 20 19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1
  1. For assigning sequences with step sizes other than 1, use the command “seq”
z<-seq(1,2,by=0.1) # array from 0 to 2 with step size 0.1
z
##  [1] 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0
  1. In order to assign an array of a given length with the same number in all elements, use
m = rep(a,l) # creates an arrey with l elements (see above l=11) all containing a (which is 2, see above)
m
##  [1] 2 2 2 2 2 2 2 2 2 2 2

Note: Arrays can be multi-dimensional, but they are not a mathematical matrix (see last section below for more details). In order to assign values to a matrix() use the command matrix. Matrices can only contain numerical elements.

M = matrix(l,a,a) # creates a matrix with a rows and a columns all containing l
M
##      [,1] [,2]
## [1,]   11   11
## [2,]   11   11

Combining arrays

Working with data, you sometimes want to add or merge information. Here is how to do it.

Arrays can be combined to yield new arrays using cbind() oder rbind() , example

X <- cbind(height,DBH)  # cbind -> columnwise binding 
X
##       height  DBH
##  [1,]     35 0.61
##  [2,]     31 0.61
##  [3,]     32 0.54
##  [4,]     33 0.54
##  [5,]     31 0.48
##  [6,]     29 0.47
##  [7,]     27 0.44
##  [8,]     26 0.43
##  [9,]     25 0.39
## [10,]     23 0.39
Y <- rbind(height,DBH)  # rbind -> rowwise binding
Y
##         [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9] [,10]
## height 35.00 31.00 32.00 33.00 31.00 29.00 27.00 26.00 25.00 23.00
## DBH     0.61  0.61  0.54  0.54  0.48  0.47  0.44  0.43  0.39  0.39

The result is really different, checkt it out closely! One option adds a new column, creating now a two-dimensional array of two onedimensional ones. The second results just in a longer one-dimensional array.

Also in two dimensional variables elements can be accessed using “[ ]”. The first number indicates the row index, the second the column index:

X[2,1]  
## height 
##     31

To obtain ALL entries in the specified row in this way:

X[3,]  
## height    DBH 
##  32.00   0.54

Take a careful look at this output: you not only see the content of line three, but also the “header” of the columns. R has not only extracted the rows, but also dragged along the information on what they mean. Those are called “attributes” and with some operations they stick to the new forms.

Collecting your works in “Scripts”

You are making progress! Before proceeding to more complex commands, let us first look into ways to collect a set of commands in “Scripts”.

Scripts are textfiles that list commands in the order they shall be executed. They work like a computer program. The difference to a programming language (like C++, fortran or java) is the active console in R, where you can paste the same commands in the console at the prompt (“>”) and obtain an answer immidiately. This is how R is an “interpreted language”, interpretation of the commands into machine language is done “life” and you can interact with the variables at the prompt. Other interpreted script languages are Python and Matlab.

Thus, scripts are just a collection of work you could also do at the prompt, but they are comfortably noted down in a text file that can also be exectuted on its own. That file is the script.

Scripts are saved as plain text files with the ending “.r” oder “.R”.

CAUTION: R speaks Englisch - script names should not contain any special German characters (“Umlaute”) and the decimal seperator is a dot (“.”) not a comma (,).

There are many ways to create a new script file in RStudio, one of them is to go to the “File” menu at the top, select “New File” and chose “R-Script”. This will open an empty page in the RStudio “editor” usually in the top left, above the console. In the “File” menue you can also save the script in a suitable directory.

Task

Try it. Create an empty R-Script, save it with a suitable name and location.

Now fill the script. It is good practice to start the script by erasing all variables potentially still in memory in the environment. This is done using the following command: rm(list=ls()) in the first line.

Next collect some of the commands executed above into the new script: Create the variabls (arrays) Species, height and DBH (copy this file above to the script). Please erase the last line from the array “height”, such that it has only 10 entries.

Have a look. Observe that the text takes different colors, those are highlighted by RStudio to help reading. The green content behind the symbol “#” are “comments” to the commands in black. Comments are not interpreted by the console, they are used to explain the syntax in human language. Use comments also to guide through your code and structuring it.

For executing or “running” a script there are several options. Some of them assume that the scipt “lives” in your “working directory”. The working directory is the place, where R looks for input and writes output to. Therefore, before proceeding, set your working directory. You do this as follows (example is for my current path, so please adjust):

setwd("~/Documents/Teaching/ShortCourses/RIntro")

Alternatively in the window containing the Tabs “Files”, “Plots”, “Help”, “Viewer” (likely on your right), chose the “File” tab and navigate in the browser to the directory where you saved your R-Script. Under “More” chose “set as working directory”. At the same place you can click on any of the script files to open them in the RStudio editor.

To now finally run the commands in the script do one of the following:

  1. Execute line by line: In the editor, move the curser to the line you want to execute. In the top right of the editor window, klick “Run”. This will exectute the line where the curser is. Alternatively, hit together “CRTL” and “Enter” (windows) or “Command” and “Enter” (Mac)

  2. Execute the entire script: In the editor click on “Source” (top right)

  3. Execute the entire script without opening it in the editor: at the console propmpt type `source(‘filename.r’) and hit enter.

All assignments requiring R should be handed in as well commented scripts that run completely and without error.

Dataframes

Now that you are ready to collect commands in a script, let us proceed to learn how to deal with larger datasets in R in “dataframes”. Dataframes are like an excel table: a collection of arrays (columns) with different data types into one table.

Collecting different arrays into a datafram is done with the command data.frame(array1, array2,array3) (the arrays should exist and be of the same length)

TREES <- data.frame(Species, height, DBH)   
TREES   
##    Species height  DBH
## 1    Beech     35 0.61
## 2    Beech     31 0.61
## 3      Oak     32 0.54
## 4    Beech     33 0.54
## 5      Oak     31 0.48
## 6    Beech     29 0.47
## 7    Beech     27 0.44
## 8      Oak     26 0.43
## 9    Beech     25 0.39
## 10     Oak     23 0.39

Accessing single elements can be done using indices in backets (see above) plus by referrring to the names of the columns using the $ sign, as follows (do this in the console only):

TREES$Species   
##  [1] "Beech" "Beech" "Oak"   "Beech" "Oak"   "Beech" "Beech" "Oak"   "Beech"
## [10] "Oak"
TREES$height    
##  [1] 35 31 32 33 31 29 27 26 25 23
TREES$DBH   
##  [1] 0.61 0.61 0.54 0.54 0.48 0.47 0.44 0.43 0.39 0.39

Plotting

R and its many packages have plenty of options for plotting. Here are just the very basics, and those will suffice for most of the work done here. A very common more advanced packate for plotting is called ggplot.

The most basic function for graphical output is called plot(). For example:

plot(TREES$DBH~TREES$height)    # Plots variable DBH versus height

Similarly, one can also plot the output of equations:

x <- 1:20   
y <- log(x) 
plot(x,y)   

Note: The plot function is highly adaptive and gives different results, depending on the data handed over in parantheis. Example: Handing the plot function a dataframe (instead of two arrays) yields a more complex graphical output

plot(TREES) # indicates that there may be a relation between column height and column dbh

In order to make nicer plots, you can also hand axis lables usinf xlab and ylab arguments in addition to the data to the function.

plot(DBH~height, data=TREES, xlab="Tree height [m]", ylab="Brusthoehendurchmesser [m]")

Find out more on what is possible by using ?plot at the prompt.

Task Append the commands defining the dataframe and plottin it to your script. Add short comments to give a short hint, what the command does. This is the end of your first script. Finalize and save, and check whether it runs and creates the plot.

Importing data from a file, and your first analysis

Most of the time, we will want to work with measurements that are stored in tables outside of R. This section is about how to reading those.

You can import data from the working directory directly or indicate the path to the file.

You need to be aware of the structure of the data file. It typically consists of a table (e.g. several columns of data) contained in a text file. Well common are comma separated files (extension “.csv”). The column delimitor is a comma (in German Excel sometimes “;”) and the decimal sperator a dot “.”.

Importing the data can be done with the funktion read.table(filename, sep = , dec=" ", header = ).

Task Start a new script in your working directory. Download the file “TreeProps.csv” provided and place it in the working directory. In the script copy the commands (below) to import the data and plot them. Make sure you start your script by clearing the existing variables, using rm(list=ls()) and setting the workspace, as shown above.

The data file “TreeProps.csv” contains the following tree properties for a larger number of trees (tree survey of 1 ha forest plot):

The file is formatted according to international standards. Its separator is “,” and decimal sign is “.”, the file first line is a header. Here is how to import.

dataset <- read.table("TreeProps.csv",sep ="," , dec =".", header=TRUE )

The arguments in “sep” indicates column separator and “dec” the decimal sign. The argument “header” is set either TRUE as the first line of the file is a header (should be set to FALSE otherwise).

When reading data from a German-speaking Excel (seperator is “;” and decimal seperatpr is “,”). This format can also imported quickly using the specialized function read.csv2() instead of read.table.

The function automatically imports the file to a dataframe. Look at the structure (remeber the function str()) to get an overview, or double klick on “dataset” on the right in the Environment window. Check whether all columns that are supposed to be numerical also recognized as numbers?

str(dataset)
## 'data.frame':    253 obs. of  4 variables:
##  $ Tree_ID : int  1 2 3 4 5 6 8 10 11 12 ...
##  $ DBH_m   : num  0.45 0.32 0.59 0.38 0.15 0.3 0.34 0.73 0.38 0.1 ...
##  $ Species : chr  "Bi" "Bu" "Bi" "Ei" ...
##  $ Height_m: num  28.4 23.8 31.1 29.6 9.7 ...

Let us plot the relation between diameter at breast height and und tree height only for beech trees marked “Bu” in the column “Species”. We will use the filtering trick seen above.

Extract only the beech data from the dataframe: Select only the rows, which have the entry “Bu” in column “Species”. And plot only for this data the diameter at breast height vs. tree height.

Bu_data<-dataset[which(dataset$Species=="Bu"),] 
plot(Bu_data$DBH_m,Bu_data$Height_m,xlab="Diameter at breast height [m]", ylab="Tree height [m]")

Congratulations, you finished your second script. Check whether you understood all commands? All were introduced above, but they may look different now.Try running it in one piece. Add some comments.

Control elements: Loops and conditions

You are now ready to work with data and do this in scripts. In the following we will now deal more with commands that help operate with data: “Control elements”. They are extremely helpful in all programming and we will need them a great deal.

Control elements consist of blocks of code that only make sense when they are complete. Therfore, to execute the elements below, please either paste the entire block to the prompt, or copy to a script and run it entirely. In the script you can also highlight the entire code block and hit together and .

FOR loop (preferred!)

Repeats the interior code or operation for a predefined number of counted iterations. The interior is framed by curly brackets:

Example:

x=1

for (i in 2:5) {    # will be repeated for i running from 2 to 5 (2,3,4,5 = 4 times)
    x[i] <- x[i-1]+1
}   
x
## [1] 1 2 3 4 5

Do you recognize what this does? Try formulatin in words.

Here is an example for a more complicated loop. This is just for illustration. The same operation could be programmed in a shorter way.

a <- c(1:3) # initialize variable a -> this is the variable that will sequentially be overwritten.

for (i in 1:length(a)) { # this is a flexible or "soft" way to count, if the size of a changes, the loop will adapt
  a[i] <- a[i]^2
  print(i) # print forces to show the content of the variable within the loop
  print(a)
  }
## [1] 1
## [1] 1 2 3
## [1] 2
## [1] 1 4 3
## [1] 3
## [1] 1 4 9

As stated above, the same result can be obtained in an easier way, without a loop. Can you think of it? Understanding in which situations a loop is required vs not required is one of the major challenges you will be facing in the labs. I sometimes give a hint, like “you will require a loop”.

WHILE loop (not preferred!)

The while loop may seem more intuitive, but it is actually more errorprone. It is just introduced here for completeness to illustrate the difference with a for loop. Do not use it! A while-loop exectutes the interior until as long as a logical expression (condition) yields “true”.

x=1
while (x < 30) {    # start the while loop, check whether x is larger than 30
    x <- x+1 # replace x by x+1 =  count x one up
}   
x
## [1] 30

Conditions - IF statement

An “IF statement” allows execution of code only if a condition is fullfilled. A thing you will use a lot. Conditions require the use of logical signs, such as: == “is equal”, > “is larger as” or >= “is equal or larger as” or != “is not equal to”. BTW, these are the same signs that can be used for the (conditional) function which() introduced above.

x=30 # intialize x. Try changing this, as see what happens
if (x == 1) {   
  print('x is equal to 1')
} else {    
    print('x is not equal 1, x='); print(x)
}   
## [1] "x is not equal 1, x="
## [1] 30

Final note on Martrices and Linear Algebra

We will be using methods of Linear Algebra in some instances and their handling in a programming language requires some attention. Therefore here a note. More practical information is available here # http://www.r-tutor.com/r-introduction/matrix/matrix-construction

I encourage you to first work on repeating Linear Algebra, and working through this section only after this.

Assume you have assigned a two dimensional structure in R with specific values, you can do using (a) using cbind

A = cbind(c(1,2,3),c(4,5,6),c(7,8,9))
A
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9
  1. using the command “c()” and “martrix”, which is quicker :)
B=matrix(c(1:9),nrow=3,ncol=3) # note: ncol*nrow=length(c(1:9))
B
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    2    5    8
## [3,]    3    6    9

You can now calculate.

Addition

C=A+B
C
##      [,1] [,2] [,3]
## [1,]    2    8   14
## [2,]    4   10   16
## [3,]    6   12   18

Matrix multiplication, e.g. Multiplication according to the rules of linear Algebra

D=A%*%B

Careful #1: This is not the same as elementwise multiplication, which is possible in R but not a matrix operation in linear algebra (if you do not know what I am talking about, you may have to do some reading on linear algebra) Elementwise multiplications yields the following result

E=A*B

Careful #2: An array, like

b = (c(1,2,3))
b
## [1] 1 2 3

is not a vector that can be used for calculation in linear algebra, because it is an object of type “array” and not “vector”. You can however transform it into the required object type, by specifically defining it as matrix (a one dimensional in this case). Thankfully, this is done easily as follows:

b2<-as.matrix(b) # transformierms b into a column vector, 
b2                # note the change to the first b above!
##      [,1]
## [1,]    1
## [2,]    2
## [3,]    3

Now vector b2 can be multiplied with matrix A, yielding a resonable result

c <- A%*%b2
c
##      [,1]
## [1,]   30
## [2,]   36
## [3,]   42

Changing the order in this case will not work btw, since this is not a defined matrix operation (this is another rule in linear algebra, worthwhile looking up, if you do not remember it)

# d <- b2%*%A

Here lies a potential source of error: If b is accidentally defined as an array, multiplication (with a “normal” sign “" instead of "%%”) in this order does work in R. HOWEVER, this is not a matrix multiplication, but elementwise multiplication and gives a totally different result, which may not be what you wanted to do.

b = (c(1,2,3))
F <- b*A
F
##      [,1] [,2] [,3]
## [1,]    1    4    7
## [2,]    4   10   16
## [3,]    9   18   27

Thus: Do take care with operations and types of variables. R does work logically and faithfully, but it does not think for you : )

You can also perform operation on matrices:

G <- A+2
G
##      [,1] [,2] [,3]
## [1,]    3    6    9
## [2,]    4    7   10
## [3,]    5    8   11

Here are some more operations that are performed elementwise in R

(b2 <- b^3) # third power
## [1]  1  8 27
(b3 <- sqrt(b)) # square root
## [1] 1.000000 1.414214 1.732051
(b4 <- log(b))  # natural logarithm (ln)
## [1] 0.0000000 0.6931472 1.0986123
(b5 <- log(b,base=2)) # logarithm to base 2
## [1] 0.000000 1.000000 1.584963
(b6 <- sin(b)) # Sine of b 
## [1] 0.8414710 0.9092974 0.1411200

many more

Finally, you can obtain the dimensions of a matrix with the command dim():

dim(X)  
## [1] 10  2

Much success!!