Introduction to R

Back to main page.

What Is R?

Why Use R?

Wouldn’t Something Menu-Driven Be Easier?

Rhesus Monkey Grooming Network

require(igraph)
rhesus <- read.table("https://web.stanford.edu/class/earthsys214/data/sade1.txt", 
                     skip=1, header=FALSE)
rhesus <- as.matrix(rhesus)
nms <- c("066", "R006", "CN", "ER", "CY", "EC", "EZ", "004", "065", "022", "076", 
         "AC", "EK", "DL", "KD", "KE")
sex <- c(rep("M",7), rep("F",9))
dimnames(rhesus)[[1]] <- nms
dimnames(rhesus)[[2]] <- nms
grhesus <- graph_from_adjacency_matrix(rhesus, weighted=TRUE)
V(grhesus)$sex <- sex

rhesus.layout <- layout.kamada.kawai(grhesus)
plot(grhesus, edge.width=log10(E(grhesus)$weight)+1, vertex.label=V(grhesus)$name,
     vertex.color=as.numeric(V(grhesus)$sex=="F")+5, layout=rhesus.layout)

A Few Conventions and Other Helpful Bits

# a comment
x <- c(1,2,3)
(y <- c(1,2,3))
## [1] 1 2 3

R as a Calculator

# addition
2+2
## [1] 4
# multiplication
2*3
## [1] 6
a <- 2
b <- 3
a*b
## [1] 6
# division
2/3
## [1] 0.6666667
b/a
## [1] 1.5
1/b/a
## [1] 0.1666667
# note order of operations!
1/(b/a)
## [1] 0.6666667
# parentheses can override order of operations
# an exponential
exp(-2)
## [1] 0.1353353
# why we age
r <- 0.02
exp(-r*45)
## [1] 0.4065697
# something more tricky
exp(log(2))
## [1] 2
# generate 20 normally distributed random numbers
rnorm(20)
##  [1] -1.1557722  0.2570493  1.2948309 -1.2080677  0.3102673  0.3369799
##  [7]  0.6387551  0.4450958  0.7512179 -1.2697104 -1.6181953  2.4480412
## [13]  0.4990785  1.5609338 -0.7308042 -0.2782639 -1.4443380  0.9956934
## [19] -2.0220970 -1.7860527

Data Types

Numeric

All numbers in R are of the form double (i.e., double-precision floating point numbers). This can be a bit confusing for people who are used to languages with integer data types (like, most languages!). Entering something that looks like an integer doesn’t mean it is.

# it looks like an integer, but don't be fooled!
a <- 2
is.numeric(a)
## [1] TRUE
is.integer(a)
## [1] FALSE
is.double(a)
## [1] TRUE

Integer

OK, technically R does have an integer class, but it is used very rarely and many functions will convert integers into doubles anyway. If you really must have an integer (e.g., because you are passing output to external C or FORTRAN code that expects it), add the suffix L to the entered number.

a <- 2L
is.integer(a)
## [1] TRUE

Character

Strings are represented by the character data class.

(countries <- c("Uganda", "Tanzania", "Kenya", "Rwanda"))
## [1] "Uganda"   "Tanzania" "Kenya"    "Rwanda"
as.character(1:5)
## [1] "1" "2" "3" "4" "5"

Factor

Factors are a data type for encoding categorical data. Notice that factors are printed without the quotes. This is because R stores them as a set of codes. Data of type “factor” are different from data of type “character” (which is what plain text is). Note the difference below between factor and character data. Because factors get used in statistical models, they are actually represented as numbers (the levels) that have associated names. Vectors, on the other hand, are just lists of numbers.

countries <- factor(c("Uganda", "Tanzania", "Kenya", "Rwanda"))
countries
## [1] Uganda   Tanzania Kenya    Rwanda  
## Levels: Kenya Rwanda Tanzania Uganda
# a trick to get some insight into how factors are handled by R
unclass(countries)
## [1] 4 3 1 2
## attr(,"levels")
## [1] "Kenya"    "Rwanda"   "Tanzania" "Uganda"
countries1 <- c("Uganda", "Tanzania", "Kenya", "Rwanda")
countries1 == unclass(countries1)
## [1] TRUE TRUE TRUE TRUE
countries == unclass(countries)
## [1] FALSE FALSE FALSE FALSE

Logical

TRUE and FALSE are reserved keywords, while T and F are global constants set to these. These logical variables are essential tools for subsetting data. You also use them extensively in setting optional arguments of functions.

t.or.f <- c(T,F,F,T,T)
is.logical(t.or.f)
## [1] TRUE
aaa <- c(1,2,3,4,5)
# subset
aaa[t.or.f]
## [1] 1 4 5

List

You can mix different types of data in a list using the command list(). This is useful when you write your own functions and want to output multiple things. Use the function str() to give you information about a list.

child1 <- list(name="mary", child.age=6,
status="foster",mother.alive=F, father.alive=T, parents.ages=c(24,35))
str(child1)
## List of 6
##  $ name        : chr "mary"
##  $ child.age   : num 6
##  $ status      : chr "foster"
##  $ mother.alive: logi FALSE
##  $ father.alive: logi TRUE
##  $ parents.ages: num [1:2] 24 35

Coercion

countries <- factor(c("Uganda", "Tanzania", "Kenya", "Rwanda"))
as.character(countries)
## [1] "Uganda"   "Tanzania" "Kenya"    "Rwanda"
as.numeric(countries)
## [1] 4 3 1 2
# werk it backwards
countries1 <- c("Uganda", "Tanzania", "Kenya", "Rwanda")
as.factor(countries1)
## [1] Uganda   Tanzania Kenya    Rwanda  
## Levels: Kenya Rwanda Tanzania Uganda
# sometimes you want your numbers to actually be strings (e.g., when you make labels or column names)
as.character(1:5)
## [1] "1" "2" "3" "4" "5"
# there actually is an integer class; it just doesn't get used much at all
a <- 2
is.integer(a)
## [1] FALSE
is.integer(as.integer(a))
## [1] TRUE

Creating Vectors

( manual <- c(1,3,5,7,9))
## [1] 1 3 5 7 9
( count <- 1:20 )
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
( ages <- seq(0,85,by=5) )
##  [1]  0  5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85
( ones <- rep(1,10) )
##  [1] 1 1 1 1 1 1 1 1 1 1
( fourages <- rep(c(1,2),c(5,10)) )
##  [1] 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2
( equalspace <- seq(1,5, length=20) )
##  [1] 1.000000 1.210526 1.421053 1.631579 1.842105 2.052632 2.263158
##  [8] 2.473684 2.684211 2.894737 3.105263 3.315789 3.526316 3.736842
## [15] 3.947368 4.157895 4.368421 4.578947 4.789474 5.000000
rep(2,10)
##  [1] 2 2 2 2 2 2 2 2 2 2
rep(c(1,2),10)
##  [1] 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2
rep(c(1,2), c(5,10))
##  [1] 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2
rep("R roolz!", 3)
## [1] "R roolz!" "R roolz!" "R roolz!"

Creating Matrices

# age distribution of Gombe chimps in 1980 and 1986
cx1980 <- c(7, 13, 8, 13, 5, 35, 9)
cx1988 <- c(9, 11, 15, 8, 9, 38, 0)
( C <- cbind(cx1980, cx1988) )
##      cx1980 cx1988
## [1,]      7      9
## [2,]     13     11
## [3,]      8     15
## [4,]     13      8
## [5,]      5      9
## [6,]     35     38
## [7,]      9      0
# another way
C <- c(cx1980, cx1988)
(  C <- matrix(C, nrow=7, ncol=2) )
##      [,1] [,2]
## [1,]    7    9
## [2,]   13   11
## [3,]    8   15
## [4,]   13    8
## [5,]    5    9
## [6,]   35   38
## [7,]    9    0
# age distribution at Tai; Boesch uses fewer age classes
cx.boesch <- c(18,10,15,30)
( C <- cbind(C,cx.boesch) )
## Warning in cbind(C, cx.boesch): number of rows of result is not a multiple
## of vector length (arg 2)

##            cx.boesch
## [1,]  7  9        18
## [2,] 13 11        10
## [3,]  8 15        15
## [4,] 13  8        30
## [5,]  5  9        18
## [6,] 35 38        10
## [7,]  9  0        15
( X <- matrix(1,nr=3,nc=3) )
##      [,1] [,2] [,3]
## [1,]    1    1    1
## [2,]    1    1    1
## [3,]    1    1    1
# cross-classified data on hair/eye color 
freq <- c(32,11,10,3,  38,50,25,15,  10,10,7,7,  3,30,5,8)
hair <- c("Black", "Brown", "Red", "Blond")
eyes <- c("Brown", "Blue", "Hazel", "Green")
freqmat <- matrix(freq, nr=4, nc=4, byrow=TRUE)
dimnames(freqmat)[[1]] <- hair
dimnames(freqmat)[[2]] <- eyes
freqmat
##       Brown Blue Hazel Green
## Black    32   11    10     3
## Brown    38   50    25    15
## Red      10   10     7     7
## Blond     3   30     5     8
# might as well do something with it
mosaicplot(freqmat)

Data Frames

# five columns of data
satu <- c(1,2,3,4,5)
dua <- c("a","b","c","d","e")
tiga <- sample(c(TRUE,FALSE),5,replace=TRUE)
empat <- LETTERS[7:11]
lima <- rnorm(5)
# construct a data frame
(collection <- data.frame(satu,dua,tiga,empat,lima))
##   satu dua  tiga empat       lima
## 1    1   a  TRUE     G -0.6938473
## 2    2   b  TRUE     H -0.0320666
## 3    3   c FALSE     I -0.5536300
## 4    4   d  TRUE     J -1.2437099
## 5    5   e FALSE     K  0.4473392
# extract the third variable
collection$tiga
## [1]  TRUE  TRUE FALSE  TRUE FALSE

Directories and Paths

getwd()
setwd("/Users/jhj1/Teaching/social_networks/")

Reading Files

# read a space-delimitted file (a sociomatrix of kids 17 kids aggressive acts toward each other)
(kids <- read.table("https://web.stanford.edu/class/earthsys214/data/strayer_strayer1976-fig2.txt", header=FALSE))
##    V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17
## 1   0  1  3  4  1  0  0  1  1   0   1   0   7   0   1   0   0
## 2   1  0  7  8  2  1  1 12  3   0   1   1   4   1   0   0   2
## 3   1  4  0  7  3  2  2  0  1   0   8   1   5   5   0   0   1
## 4   3  3  2  0  3  1 13  3  5   1   0   0   8   3   0   2   1
## 5   1  0  0  3  0  4  6  0  8   5   1   0   1   3   0   2   1
## 6   0  0  0  0  0  0  2  8 11   0   4   0   4   3   0   1   0
## 7   1  0  1  9  3  4  0  2  0   0   1   0   7   9   1   1   0
## 8   0  0  0  1  1  1  2  0  7   5   1   1   1   0   0   0   0
## 9   1  1  1  2  5 11  0  3  0   0   0   0   1   0   0   0   0
## 10  0  0  0  0  0  0  1  0  0   0   0  11   0   1   0   1   4
## 11  4  0  4  3  3  2  1  0  0   0   0   3  11   5   0   2   2
## 12  0  0  0  0  0  0  0  0  0   2   0   0   2   0   8   0   0
## 13  0  1  9  3  0  3  6  0  0   0  11   2   0   1   0   7   5
## 14  0  1  4  0  1  2  1  0  0   0   1   0   1   0   0   0   0
## 15  0  0  0  0  0  0  0  0  0   0   0   3   0   0   0   0   0
## 16  0  0  0  0  0  1  0  0  0   0   0   1   1   0   0   0   0
## 17  0  0  0  0  0  0  0  0  1   1   0   0   0   0   0   0   0
quercus <- read.delim("https://web.stanford.edu/class/earthsys214/data/quercus.txt", skip=24, sep="\t", header=TRUE)
head(quercus)
##                     Species   Region Range acorn.size tree.height
## 1           Quercus alba L. Atlantic 24196        1.4          27
## 2  Quercus bicolor Willd.   Atlantic  7900        3.4          21
## 3 Quercus macrocarpa Michx. Atlantic 23038        9.1          25
## 4  Quercus prinoides Willd. Atlantic 17042        1.6           3
## 5         Quercus Prinus L. Atlantic  7646       10.5          24
## 6    Quercus stellata Wang. Atlantic 19938        2.5          17

The Workspace

objects()
##  [1] "a"             "aaa"           "ages"          "b"            
##  [5] "C"             "child1"        "collection"    "count"        
##  [9] "countries"     "countries1"    "cx.boesch"     "cx1980"       
## [13] "cx1988"        "dua"           "empat"         "equalspace"   
## [17] "eyes"          "fourages"      "freq"          "freqmat"      
## [21] "grhesus"       "hair"          "kids"          "lima"         
## [25] "manual"        "nms"           "ones"          "quercus"      
## [29] "r"             "rhesus"        "rhesus.layout" "satu"         
## [33] "sex"           "t.or.f"        "tiga"          "x"            
## [37] "X"             "y"
rm(aaa)
rm(list=ls())
objects()
## character(0)

Scope

quercus <- read.delim("https://web.stanford.edu/class/earthsys214/data/quercus.txt", skip=24, sep="\t", header=TRUE)
plot(quercus$tree.height, quercus$acorn.size, pch=16, col="red", xlab="Tree Height (m)", ylab="Acorn Size (cm3)")

quercus <- read.delim("https://web.stanford.edu/class/earthsys214/data/quercus.txt", skip=24, sep="\t", header=TRUE)
with(quercus, plot(tree.height, acorn.size, pch=16, col="blue", xlab="Tree Height (m)", ylab="Acorn Size (cm3)"))

Indexing and Subsetting

myvec <- c(1,2,3,4,5,6,66,77,7,8,9,10)
myvec[1]
## [1] 1
myvec[1:5]
## [1] 1 2 3 4 5
myvec[-1]
##  [1]  2  3  4  5  6 66 77  7  8  9 10
myvec[-(1:5)]
## [1]  6 66 77  7  8  9 10
# try without the parentheses
#myvec[-1:5]
myvec[c(2,5,1,11)]
## [1] 2 5 1 9
quercus <- read.delim("https://web.stanford.edu/class/earthsys214/data/quercus.txt", skip=24, sep="\t", header=TRUE)
dim(quercus)
## [1] 39  5
size <- quercus$acorn.size
size[1:3] #first 3 elements
## [1] 1.4 3.4 9.1
size[17]  #only element 17
## [1] 4.8
size[-39] #all but the last element
##  [1]  1.4  3.4  9.1  1.6 10.5  2.5  0.9  6.8  1.8  0.3  0.9  0.8  2.0  1.1
## [15]  0.6  1.8  4.8  1.1  3.6  1.1  1.1  3.6  8.1  3.6  1.8  0.4  1.1  1.2
## [29]  4.1  1.6  2.0  5.5  5.9  2.6  6.0  1.0 17.1  0.4
size[c(3,6,9)] # elements 3,6,9
## [1] 9.1 2.5 1.8
size[quercus$Region=="California"] # use a logical test to subset
##  [1]  4.1  1.6  2.0  5.5  5.9  2.6  6.0  1.0 17.1  0.4  7.1
quercus[3,4] # access an element of an array or data frame by X[row,col]
## [1] 9.1
quercus[,"tree.height"]
##  [1] 27.0 21.0 25.0  3.0 24.0 17.0 15.0  0.3 24.0 11.0 15.0 23.0 24.0  3.0
## [15] 13.0 30.0  9.0 27.0  9.0 24.0 23.0 27.0 24.0 23.0 18.0  9.0  9.0  4.0
## [29] 18.0  6.0 17.0 20.0 30.0 23.0 26.0 21.0 15.0  1.0 18.0

More Subsetting

myvec <- c(1,2,3,4,5,6,66,77,7,8,9,10)
myvec <- myvec[myvec<=10]
myvec
##  [1]  1  2  3  4  5  6  7  8  9 10
x <- 1:7
# elements that are greater than 2 but less than 6
(x>2) & (x<6)
## [1] FALSE FALSE  TRUE  TRUE  TRUE FALSE FALSE
# this is not intuitive
(x>2) && (x<6)
## [1] FALSE
# but dis doe...
(x<2) && (x<6)
## [1] TRUE
is.even <- rep(c(FALSE, TRUE),5)
(evens <- myvec[is.even])
## [1]  2  4  6  8 10

Missing Values

aaa <- c(1,2,3,NA,4,5,6,NA,NA,7,8,9,NA,10)
aaa <- aaa[!is.na(aaa)]
aaa
##  [1]  1  2  3  4  5  6  7  8  9 10
aaa <- c(1,2,3,NA,4,5,6,NA,NA,7,8,9,NA,10)
is.na(aaa)
##  [1] FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE
## [12] FALSE  TRUE FALSE
!is.na(aaa)
##  [1]  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE
## [12]  TRUE FALSE  TRUE

Summarizing Data

aaa <- rpois(100,5)
table(aaa)
## aaa
##  0  1  2  3  4  5  6  7  8  9 10 11 
##  1  7 11  9 17 18 14 10  8  3  1  1
donner <- read.table("https://web.stanford.edu/class/earthsys214/data/donner.dat", header=TRUE, skip=2)
# survival=0 == died; male=0 == female
with(donner, table(male,survival))
##     survival
## male  0  1
##    0  5 10
##    1 20 10
# table along 3 dimensions
with(donner, table(male,survival,age))
## , , age = 15
## 
##     survival
## male 0 1
##    0 0 1
##    1 1 0
## 
## , , age = 18
## 
##     survival
## male 0 1
##    0 0 0
##    1 0 1
## 
## , , age = 20
## 
##     survival
## male 0 1
##    0 0 1
##    1 0 1
## 
## , , age = 21
## 
##     survival
## male 0 1
##    0 0 1
##    1 0 0
## 
## , , age = 22
## 
##     survival
## male 0 1
##    0 0 1
##    1 0 0
## 
## , , age = 23
## 
##     survival
## male 0 1
##    0 0 1
##    1 2 1
## 
## , , age = 24
## 
##     survival
## male 0 1
##    0 0 1
##    1 1 0
## 
## , , age = 25
## 
##     survival
## male 0 1
##    0 1 1
##    1 5 1
## 
## , , age = 28
## 
##     survival
## male 0 1
##    0 0 0
##    1 2 2
## 
## , , age = 30
## 
##     survival
## male 0 1
##    0 0 0
##    1 3 1
## 
## , , age = 32
## 
##     survival
## male 0 1
##    0 0 2
##    1 0 1
## 
## , , age = 35
## 
##     survival
## male 0 1
##    0 0 0
##    1 1 0
## 
## , , age = 40
## 
##     survival
## male 0 1
##    0 0 1
##    1 1 1
## 
## , , age = 45
## 
##     survival
## male 0 1
##    0 2 0
##    1 0 0
## 
## , , age = 46
## 
##     survival
## male 0 1
##    0 0 0
##    1 0 1
## 
## , , age = 47
## 
##     survival
## male 0 1
##    0 1 0
##    1 0 0
## 
## , , age = 50
## 
##     survival
## male 0 1
##    0 1 0
##    1 0 0
## 
## , , age = 57
## 
##     survival
## male 0 1
##    0 0 0
##    1 1 0
## 
## , , age = 60
## 
##     survival
## male 0 1
##    0 0 0
##    1 1 0
## 
## , , age = 62
## 
##     survival
## male 0 1
##    0 0 0
##    1 1 0
## 
## , , age = 65
## 
##     survival
## male 0 1
##    0 0 0
##    1 1 0
cage <- rep(0,length(donner$age))
# simplify by defining 2 age classes: over/under 25
cage[donner$age<=25] <- 1
cage[donner$age>25] <- 2
donner <- data.frame(donner,cage=cage)
with(donner, table(male,survival,cage))
## , , cage = 1
## 
##     survival
## male  0  1
##    0  1  7
##    1  9  4
## 
## , , cage = 2
## 
##     survival
## male  0  1
##    0  4  3
##    1 11  6
aaa <- rpois(100,5)
sort(aaa)
##   [1]  1  1  1  1  2  2  2  2  2  2  2  2  3  3  3  3  3  3  3  3  3  3  3
##  [24]  3  4  4  4  4  4  4  4  4  4  4  4  5  5  5  5  5  5  5  5  5  5  5
##  [47]  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  6  6  6  6  6  6  6  6
##  [70]  6  6  6  6  6  6  6  6  7  7  7  7  7  7  8  8  8  8  8  8  8  8  8
##  [93]  8  9  9  9  9 10 10 13
# decreasing order
sort(aaa,decreasing=TRUE)
##   [1] 13 10 10  9  9  9  9  8  8  8  8  8  8  8  8  8  8  7  7  7  7  7  7
##  [24]  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  6  5  5  5  5  5  5  5
##  [47]  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  4  4  4  4
##  [70]  4  4  4  4  4  4  4  3  3  3  3  3  3  3  3  3  3  3  3  2  2  2  2
##  [93]  2  2  2  2  1  1  1  1
# five columns of data again
satu <- c(1,2,3,4,5)
dua <- c("a","b","c","d","e")
tiga <- sample(c(TRUE,FALSE),5,replace=TRUE)
empat <- LETTERS[7:11]
lima <- rnorm(5)
# construct a data frame
(collection <- data.frame(satu,dua,tiga,empat,lima))
##   satu dua  tiga empat       lima
## 1    1   a FALSE     G  0.7277635
## 2    2   b  TRUE     H  2.0277277
## 3    3   c FALSE     I  1.9295619
## 4    4   d FALSE     J -0.1581232
## 5    5   e FALSE     K  1.4184415
o <- order(collection$lima)
collection[o,]
##   satu dua  tiga empat       lima
## 4    4   d FALSE     J -0.1581232
## 1    1   a FALSE     G  0.7277635
## 5    5   e FALSE     K  1.4184415
## 3    3   c FALSE     I  1.9295619
## 2    2   b  TRUE     H  2.0277277

Naming Data

kids <- read.table("https://web.stanford.edu/class/earthsys214/data/strayer_strayer1976-fig2.txt", header=FALSE)
kid.names <- c("Ro","Ss","Br","If","Td","Sd","Pe","Ir","Cs","Ka",
                "Ch","Ty","Gl","Sa", "Me","Ju","Sh")
colnames(kids) <- kid.names
rownames(kids) <- kid.names

Working on Lists

aaa <- list(alpha = 1:10, beta = rnorm(100), x = sample(1:100, 100, replace=TRUE))
lapply(aaa,mean)
## $alpha
## [1] 5.5
## 
## $beta
## [1] -0.1212708
## 
## $x
## [1] 50.72
# more compact as a vector
sapply(aaa,mean)
##      alpha       beta          x 
##  5.5000000 -0.1212708 50.7200000
# cross-tabulation of sex partners from NHSLS
sextable <- read.csv("https://web.stanford.edu/class/earthsys214/data/nhsls_sextable.txt", header=FALSE)
dimnames(sextable)[[1]] <- c("white","black","hispanic","asian","other")
dimnames(sextable)[[2]] <- c("white","black","hispanic","asian","other")
# calculate marginals
(row.sums <- apply(sextable,1,sum))
##    white    black hispanic    asian    other 
##     1177      278      158       26       26
(col.sums <- apply(sextable,2,sum))
##    white    black hispanic    asian    other 
##     1194      281      137       13       40
# using sapply() gives similar output
sapply(sextable,sum)
##    white    black hispanic    asian    other 
##     1194      281      137       13       40
# compare the output of sapply() to lapply()
lapply(sextable,sum)
## $white
## [1] 1194
## 
## $black
## [1] 281
## 
## $hispanic
## [1] 137
## 
## $asian
## [1] 13
## 
## $other
## [1] 40

Flow Control: if

(coin <- sample(c("heads","tails"),1))
## [1] "tails"
if(coin=="tails") b <- 1 else b <- 0
b
## [1] 1
x <- 4:-2
# sqrt(x) produces warnings, but using ifelse to check works without producing warings
sqrt(ifelse(x >= 0, x, NA))
## [1] 2.000000 1.732051 1.414214 1.000000 0.000000       NA       NA

Flow Control: for

x <- 1:5
for(i in 1:5) print(x[i])
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5

Using Packages

library(igraph)
# might as well do something with it
# a small graph
g <- graph( c(1,2, 1,3, 2,3, 3,5), n=5 )
plot(g)