<jupyter_start><jupyter_text>R tutorial This tutorial will walk you through some of the basics of R that will be helpful to understand for single cell analysis with Seurat if you are new to R.  It is largely copied from the [R tutorial](https://courses.cs.ut.ee/MTAT.03.183/2017_spring/uploads/Main/r_tutorial.html). There are other great resources for learning the basics of R which will cover more topics than this brief introductory tutorial.  Two that I'd recommend are the freely available web book: [R for Data Science](https://r4ds.had.co.nz/index.html) written by <NAME> and <NAME> and the LinkedIn Learning course [Learning R](https://www.linkedin.com/learning-login/share?account=42275329&forceAccount=false&redirect=https%3A%2F%2Fwww.linkedin.com%2Flearning%2Flearning-r-2%3Ftrk%3Dshare_ent_url%26shareId%3DIlQ%252BKm79TvWKql%252FKjfwpMQ%253D%253D) by <NAME>.  To access the LinkedIn Learning course will need to be signed into LinkedIn Learning from your Univeristy account.  You can get to LinkedIn Learning by logging into your UCDAccess account then selecting Training from the CU Resources drop down menu and clicking on the LinkedIn Learning Icon. A list of other R tutorial resouces is [here](https://bioinformatics.uconn.edu/introduction-to-r/).R is a general purpose programming language with special emphasis on statistical computing. In the following tutorial we explore R and its main functionalities. We suggest experimenting with and trying out the commands by yourself.   Table of Contents* [Help - where to get it](Help---where-to-get-it)* [Analysis with R](Analysis-with-R)* [Vectors](Vectors)* [Matrices](Matrices)* [Lists](Lists)* [Data frames](Data-frames)    - [Subsetting similar to matrices](Subsetting-similar-to-matrices)* [Other useful commands](Other-useful-commands)* [An example of exploratory data investigation with R](An-example-of-exploratory-data-investigation-with-R)* [Plotting](Plotting)  Help - where to get it If you are working in RStudio, a good way to get help for a function is to type `?function` for example for the function `log()` type `?log`.  In RStudio you can also search for a help document from the "Help" tab of the "Files/Plots/Packages/Help/Viewer" pane.  In any R environment you can also use the following. If you want to get a list of available functions with a word in their name, use `apropos()`.<jupyter_code>apropos("log")<jupyter_output><empty_output><jupyter_text>Or some examples of how to use a function.  Here we will look at examples for the function `log()`<jupyter_code>example(log)
#Also try ?log in RStudio. 
#This opens up a help page for log function and its parameters.
#Works for all the other functions too.<jupyter_output>log> log(exp(3))
[1] 3

log> log10(1e7) # = 7
[1] 7

log> x <- 10^-(1+2*1:9)

log> cbind(x, log(1+x), log1p(x), exp(x)-1, expm1(x))
          x                                                    
 [1,] 1e-03 9.995003e-04 9.995003e-04 1.000500e-03 1.000500e-03
 [2,] 1e-05 9.999950e-06 9.999950e-06 1.000005e-05 1.000005e-05
 [3,] 1e-07 1.000000e-07 1.000000e-07 1.000000e-07 1.000000e-07
 [4,] 1e-09 1.000000e-09 1.000000e-09 1.000000e-09 1.000000e-09
 [5,] 1e-11 1.000000e-11 1.000000e-11 1.000000e-11 1.000000e-11
 [6,] 1e-13 9.992007e-14 1.000000e-13 9.992007e-14 1.000000e-13
 [7,] 1e-15 1.110223e-15 1.000000e-15 1.110223e-15 1.000000e-15
 [8,] 1e-17 0.000000e+00 1.000000e-17 0.000000e+00 1.000000e-17
 [9,] 1e-19 0.000000e+00 1.000000e-19 0.000000e+00 1.000000e-19<jupyter_text>You can also try ?log.  This opens up a help page for log function and its parameters. Works for all the other functions too.<jupyter_code>?log<jupyter_output><empty_output><jupyter_text>Analysis with R In R, all values are printed in the console.  But when a value is assigned to a variable it is not printed. Try the following:<jupyter_code>2 + 2
3.4/2
#Variable assignment
## Note that # is a symbol for comments. 
#Everything after # gets ignored.
x = 3
pi
5^2-7*2<jupyter_output><empty_output><jupyter_text>We can print x or use it in a calculation. Note that when the variable x is declared and assigned a value in any other windows then you can use it in other windows too.<jupyter_code>x
x + 2
2*x^2<jupyter_output><empty_output><jupyter_text>Vectors Vectors are the most important data structure in R. Remember to declare vectors in construct `c()`. R is a vectorized language. Functions are applied to all members of the vector. This removes the need for clumsy loop constructs. Next we demonstrate some basic functions and constructs to manipulate vectors in R. Try them out.<jupyter_code>x = c(1,3,4,7) #assign vector to a variable name.
y = x + 1 #We add 1 to all members of vector x
print("Let's print y")
y 
c(48,56,79) #this will not be stored anywhere but is printed on console.<jupyter_output>[1] "Let's print y"<jupyter_text>Let's explore a few vectors created by `rep()`, `seq()` and `:`.<jupyter_code>z = rep(1,4) ##Rep is a function. See what it does by consulting the help pages.
rep_val=rep(0,10)
seq4=1:4
seq_4=-4:1

print("z")
z
print("rep_val")
rep_val
print("seq4")
seq4
print("seq_4")
seq_4
year = 2003:2007
sq=seq(1,4)
sq2=seq(2, 8, by=2)
v = seq(0, 1, by=.1)
cl_v=class(v)

seq_len5=seq(0, 1, length=5)

year
sq
sq2
v
cl_v
seq_len5<jupyter_output><empty_output><jupyter_text>It's important to know if the numerals in your vector are numbers or characters.These are numbers and can be used in calculations.<jupyter_code>asn=as.numeric(c("1","2","3"))
m = c(1,2,3,4)

asn
asn + 1
m
m + 1<jupyter_output><empty_output><jupyter_text>Because everything in a vector must be the same type, if you mix characters and numbers everything will be converted to characters.<jupyter_code>m2 = c("1","2","3", 4)
m3 = c(1,2,3,4,"5")

m2
m3

m2 + 1  # this line gives and error<jupyter_output><empty_output><jupyter_text>Vectors can be sliced.<jupyter_code>fruits = c("apples","oranges","kiwis","mangos")

fr_1=fruits[1] #first element of a vector

len_fr=length(fruits) #vector length

last_fr=fruits[length(fruits)]#last element of a vector

first_2=fruits[c(1,2)] # First two elements
first_3=fruits[1:3] #Elements 1 to 3

all_ex3=fruits[-3] #Everything exept the 3 elements

fruits
fr_1
len_fr
last_fr
first_2
first_3
all_ex3<jupyter_output><empty_output><jupyter_text>Remember vectors x, y and z defined above.  Here's some more manipulations with those.<jupyter_code>joined_vec=c(x,z) #join x and z vectors
larger_than4=x[x>=4] # All elements of x that are greater/equal than 4
fn1=sin(x[x>=4]+2)^2 + c(3)
div1=c(3,4)/2
div2=c(3,4)/c(8,9)

joined_vec
larger_than4
fn1
div1
div2
y_rev=rev(y) #reverse
w = c(10,6,8,2,10)
w_srt=sort(w)
w_ord=order(w)
#Sort y
sorted_w=w[order(w, decreasing=TRUE)]

y_rev
w
w_srt
w_ord
sorted_w<jupyter_output><empty_output><jupyter_text>Matrices Vectors can be multidimensional. In R two-dimensional vectors are matrices (arrays if three and up). To subset multidimensional vectors in R you need to specifiy subsetted columns and rows separately. This is done using squared brackets and column/row indices separated with comma eg for matrix/data frame "mat" this would be `mat[subset_rows,subset_cols]`<jupyter_code>#Some ways of declaring a matrix
mx = matrix(fruits,2,2)
mx2=matrix(c(1,2,4,3,2,5,6,7,5,11,2,3),3,4)
mx3 = matrix(c(1,2,4,3,2,5,6,7,5,11,2,3),3,4, byrow=TRUE)
mx4=matrix(rep(10,10), ncol = 5)

mx
mx2
mx3
mx4

#How many rows and columns / printed on console
print('Rownumber of mx2')
nrow(mx2)
print('Colnumber of mx2')
ncol(mx2)
#Extract subsets in matrix.
#First and second columns
mx2_col12=mx2[,c(1,2)]
#First and second rows
mx2_row12=mx2[c(1,2),]
#Multiply the first row elements by two.
mxnew=mx2[1,]*2
mx2_col2=mx2[,2]
#Extract element value in third column and first row
mx2_row1col3=mx2[1,3]
mx2_times7=mx2*7
mx_col3div2=mx2[,3]/2


mx2_col12
mx2_row12
mxnew
mx2_col2
mx2_row1col3
mx2_times7
mx_col3div2<jupyter_output><empty_output><jupyter_text>Elements in a matrix can be modified.<jupyter_code>mx2
#Change 1 row of mx2
mx2[1,] = mx2[1,]/2

mx2
mx2[,2] = rep(3,3)

mx2
mx2[,3] = 3

mx2<jupyter_output><empty_output><jupyter_text>Lists Lists can be used to store a larger number values that are different to eachother in terms of length and type.<jupyter_code>#Declare a list variable that has 4 components
person = list(surname="Mike", x=2, y=9, year=1990)
str(person)
print('Extract list element surname')
person$surname #dollar sign
complicated_list = list("a"= 1:4, "b"=1:3, "c"=matrix(1:4, nrow=2), "d"=search)
#Extract first list element
#print('First data element')
sec1=complicated_list[[1]]
#print('Extract second element in the first data structure of complicated_list')
sec2=complicated_list[[1]][2]

complicated_list$a = matrix(1, 2, 2)     # replacing a list element
complicated_list$title ='an arbitrary list' # adding an element
complicated_list$d = NULL                  # removing an element
#complicated_list
mylist <- list(a=1,b=2,c="3",d="test")  ## items in list are given names a,b,c,d
my2ndlist <- list(1,2,"3","test")  ## no given names

mylist
my2ndlist
mylist$a   ## $ can be used to select an item in the list by name
mylist[["a"]]  ## this is the equivalent
mylist[[1]]  ## so is this
my2ndlist[[3]]  ## $ won't work on this list since items weren't named
str(mylist)
complicated_list = list("a"= 1:4, "b"=1:3, "c"=matrix(1:4, nrow=2), "d"=search)
sec1=complicated_list[[1]]  #Extract first list element
sec2=complicated_list[[1]][2]  #Extract second element in the first data structur

complicated_list
sec1
sec2
complicated_list$a = matrix(1, 2, 2)     # replacing a list element
complicated_list
complicated_list$title ='an arbitrary list' # adding an element
complicated_list
complicated_list$d = NULL  # removing an element
complicated_list<jupyter_output><empty_output><jupyter_text>Data frames Most useful data structure in actual data analysis when you have multiple instances of multiple measured variables.<jupyter_code>df = data.frame(names = c("Tom","Jerry","Spike"), year=c(1994,1998,2000), x=rep(1,3), y=c(3,5,6)) 

df
df$sum=df$x + df$y
df<jupyter_output><empty_output><jupyter_text>Subsetting similar to matrices<jupyter_code>subset_col1df=df[,1] 
subset_row1_col3=df[1,3] 
cb_df=cbind(df, m = c(1,2,4)) 
rb_df=rbind(df,df) 
cl_f=class(df)

subset_col1df
subset_row1_col3
cb_df
rb_df
cl_f<jupyter_output><empty_output><jupyter_text>In statistical analyses, often you need to generate or sample data according to various statistical distributions or probabilities. (Not so much in single cell analysis)<jupyter_code>#Common distribution uniform, normal, exponential, gamma, poission, beta ...
uniform_100 = runif(100, min = 1, max = 5)
normal_100 = rnorm(100)
#Sampling can be done with function sample()
sample5_from_uniform100 = sample(uniform_100, size = 5, replace =FALSE) #random sampling
set.seed(1)

sample_0or1_100times=sample(c(0,1), 100, replace = TRUE) # sampling with replacement, 0 and 1

uniform_100
normal_100
sample5_from_uniform100
sample_0or1_100times<jupyter_output><empty_output><jupyter_text>Other useful commands<jupyter_code>#Which variables have beend declared
ls()
#Remove a variable
rm(all_ex3)
ls()
getwd()  # get working directory

# setwd() won't work in the Rkernel of jupyter notebook, 
# but it will work to change the working directory in an R script
# in an R notebook in RStudio it will change the working directory only for the current code chunk

#setwd("mypath/mynewdirectory")  # set working directory
libs=library()   # see all packages installed 
#libs  ## this can be a long output
src=search()    # see packages currently loaded
src
#writing your own function
f = function(x,y,z)
{
  res = sqrt(x^2 + y^2 + z^2)
  return(res)
}

f(3,4,5)<jupyter_output><empty_output><jupyter_text>An example of exploratory data investigation with R R base contains many default datasets.  One of the most common datasets in use is the Iris dataset.<jupyter_code>#Load it with 
data(iris)

#Let's write it into a file and read it from input. 
#This goes into your working directory.
write.table(iris,file='iris.txt',sep='\t',col.names=T,quote=F,row.names=F)
rm(iris)
#Read in the file we just wrote.
Iris=read.table('iris.txt',header=T,stringsAsFactors=F,sep='\t')<jupyter_output><empty_output><jupyter_text>Let's examine the dataset.<jupyter_code>colnames(Iris)
head(Iris)
str(Iris)
levels(Iris$Species)<jupyter_output><empty_output><jupyter_text>Note the Species column is a character type.  This doesn't have levels.  We have to change it to type factor. We can see how many different values are in Species with `unique()`.<jupyter_code>unique(Iris$Species)
Iris$Species <- as.factor(Iris$Species)
levels(Iris$Species)
str(Iris)<jupyter_output><empty_output><jupyter_text>Let's find the mean sepal width.<jupyter_code>mean(Iris$Sepal.Width)<jupyter_output><empty_output><jupyter_text>We can create new data frames which are subsets of Iris.<jupyter_code>subset1=subset(iris, Sepal.Width >= 4 & Petal.Length>1.4)
subset2=subset(iris, Sepal.Width >= 4 | (Species == 'setosa' & Sepal.Width < 3))
subset3=subset(iris, Species!="setosa" & Sepal.Width <5)

str(subset1)
str(subset2)
str(subset3)<jupyter_output>'data.frame':	2 obs. of  5 variables:
 $ Sepal.Length: num  5.7 5.2
 $ Sepal.Width : num  4.4 4.1
 $ Petal.Length: num  1.5 1.5
 $ Petal.Width : num  0.4 0.1
 $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1
'data.frame':	6 obs. of  5 variables:
 $ Sepal.Length: num  4.4 5.8 5.7 5.2 5.5 4.5
 $ Sepal.Width : num  2.9 4 4.4 4.1 4.2 2.3
 $ Petal.Length: num  1.4 1.2 1.5 1.5 1.4 1.3
 $ Petal.Width : num  0.2 0.2 0.4 0.1 0.2 0.3
 $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1
'data.frame':	100 obs. of  5 variables:
 $ Sepal.Length: num  7 6.4 6.9 5.5 6.5 5.7 6.3 4.9 6.6 5.2 ...
 $ Sepal.Width : num  3.2 3.2 3.1 2.3 2.8 2.8 3.3 2.4 2.9 2.7 ...
 $ Petal.Length: num  4.7 4.5 4.9 4 4.6 4.5 4.7 3.3 4.6 3.9 ...
 $ Petal.Width : num  1.4 1.5 1.5 1.3 1.5 1.3 1.6 1 1.3 1.4 ...
 $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 2 2 2 2 2 2 2 2 2 2 ...<jupyter_text>We can add a column to the iris data frame.<jupyter_code>iris$flower = ifelse(iris$Sepal.Length<5, "small_flower","big_flower")
head(iris)<jupyter_output><empty_output><jupyter_text>We could find the median, mean and standard deviation Sepal.Length, Sepal.Width, Petal.Length and Petal.Width using a for loop an the functions `median()`, `mean()` and `sd()`.<jupyter_code>for(i in 1:ncol(iris[,c(1:4)])) {
  print(c(median(iris[,i]), mean(iris[,i]), sd(iris[,i]))) 
}<jupyter_output>[1] 5.8000000 5.8433333 0.8280661
[1] 3.0000000 3.0573333 0.4358663
[1] 4.350000 3.758000 1.765298
[1] 1.3000000 1.1993333 0.7622377<jupyter_text>Or we could get the same information using `apply()`. `iris[,c(1:4)]` will select all rows and the first 4 columns of iris. Look up the documentation for `apply()` to see why we use the argument `2`.<jupyter_code>median_4firstcolumns=apply(iris[,c(1:4)], 2, median) 
mean_4firstcolumns=apply(iris[,c(1:4)], 2, mean)
sd_4firstcolumns=apply(iris[,c(1:4)], 2, sd) 

median_4firstcolumns
mean_4firstcolumns
sd_4firstcolumns<jupyter_output><empty_output><jupyter_text>Or if we create a named list containing the Sepal.Length, Sepal.Width, Petal.Length and Petal.Width values, we can use `lapply()` to obtain the same information.<jupyter_code>iris_list <- list()
for(name in names(iris)[1:4]){
    iris_list[[name]] <- iris[[name]]
}
median_list <- lapply(iris_list, median)
mean_list <- lapply(iris_list, mean)
sd_list <- lapply(iris_list, sd)

median_list
mean_list
sd_list<jupyter_output><empty_output><jupyter_text>Plotting Finally, just an example of a scatter plot with `ggplot()`.  All the functions previous to this have been base R functions, so we didn't need to load a package, but to access the `ggplot()` function, we first need to load `ggplot2` which we do with the `library()` function.  A library only needs to be loaded once before using any of the functions in a script.  Note that it's possible to load this `ggplot2` package because it has previously been installed in this docker image.  If you are working in RStudio on your own computer, you may need to first install a package with `install.packages()`.<jupyter_code>#install.packages("ggplot2")  Don't run this line if you are working in the docker.
library(ggplot2)
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width))+ geom_point()
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width,color = Species))+ geom_point()
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width,color = Species, size = Petal.Width))+ geom_point()
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width))+ geom_point()+facet_grid(Species~.) + ggtitle("This is a facet plot")
## you can break up a long line of code to make it more readable.
## You can put a return after a comma in a function or after a + when combining functions.
ggplot(iris, aes(x = Sepal.Length, 
                 y = Sepal.Width))+
    geom_point() + facet_grid(Species~.) + ggtitle("This is a facet plot")<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.120115009975355, 'fraction_numerical': 0.06530923600516371, 'mean_word_length': 5.10641347187388, 'pattern_counts': {'":': 0, '<': 124, '<?xml version=': 0, '>': 121, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 5, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '28', 'dir': 'jupyter-structured-clean-dedup', 'id': '226901', 'license': 'MIT', 'n_tokens_mistral': 6913, 'n_tokens_neox': 6212, 'n_words': 1955, 'path': 'workspace/intro_to_programming/R_tutorial.ipynb', 'repo_name': 'oligomyeggo/DevBio-scRNA-seq-Workshop', 'size': '17069'}