SlideShare a Scribd company logo
1 of 225
Download to read offline
R Fundamentals and
Programming Techniques
Thomas Lumley
R Core Development Team
and UW Dept of Biostatistics
Birmingham — 2006–2–27/28
What are R and S-PLUS?
• R is a free implementation of a dialect of the S language,
the statistics and graphics environment for which John
Chambers won the ACM Software Systems award. S
was consciously designed to blur the distinction between
users and programmers. S-PLUS is a commercial system
(Insightful Co) based on Bell Labs’ S.
• S is a system for interactive data analysis. It has always been
designed with interactive use in mind.
• S is a high-level programming language, with similarities
to Scheme and Python. It is a good system for rapid
development of statistical applications. For example, the
survey package was developed by one person, part time, and
is about 1.5% the size of the Census Bureau’s VPLX package
(which does less).
Why not S?
R (and S) are accused of being slow, memory-hungry, and able
to handle only small data sets.
This is completely true.
Fortunately, computers are fast and have lots of memory. Data
sets with a few tens of thousands of observations can be handled
in 256Mb of memory, and quite large data sets with 1Gb of
memory. Workstations with 32Gb or more to handle millions of
observations are still expensive (but in a few years Moore’s Law
should catch up).
Tools for interfacing R with databases allow very large data sets,
but this isn’t transparent to the user.
Why not R?
21 CFR 11, Basel 2, and similar regulatory guidelines require
tedious effort to document and verify things. Doing this for
another system is unappealing (although not intrinsically harder
than for commercial software)
R has no GUI and no commercial hand-holding services. S-PLUS
does. S-PLUS also has a number of specialised add-ons (I would
buy S-PLUS just to run S+SeqTrial if I were designing clinical
trials).
How similar are R and S-PLUS?
• For basic command-line data analysis they are very similar
• Most programs written in one dialect can be translated
straightforwardly to the other
• Most large programs will need some translation
• R has a very successful package system for distributing code
and data.
R GUIs
Not GUIs for statistics, but for files/scripts/windows etc
• built-in: Windows, Mac
• cross-platform: JGR (http://www.rosudo.org/JGR), Emacs/ESS
(http://ess.r-projet.org).
Outline
• Reading data
• Simple data summaries
• Graphics
• Scripts, Transcripts, ESS.
• Stratified data summaries
• Sweave
• More on functions (example: bootstrap)
• Debugging and optimization
• A little on objects
• Regression models: lm, glm, coxph
• Packages
Reading data
• Text files
• Stata datasets
• Web pages
• (Databases)
Much more information is in the Data Import/Export manual.
Reading text data
The easiest format has variable names in the first row
case id gender deg yrdeg field startyr year rank admin
1 1 F Other 92 Other 95 95 Assist 0
2 2 M Other 91 Other 94 94 Assist 0
3 2 M Other 91 Other 94 95 Assist 0
4 4 M PhD 96 Other 95 95 Assist 0
and fields separated by spaces. In R, use
salary <- read.table("salary.txt", header=TRUE)
to read the data from the file salary.txt into the data frame
salary.
Syntax notes
• Spaces in commands don’t matter (except for readability),
but Capitalisation Does Matter.
• TRUE (and FALSE) are logical constants
• Unlike many systems, R does not distinguish between com-
mands that do something and commands that compute a
value. Everything is a function: ie returns a value.
• Arguments to functions can be named (header=TRUE) or
unnamed ("salary.txt")
• A whole data set (called a data frame is stored in a variable
(salary), so more than one dataset can be available at the
same time.
Reading text data
Sometimes columns are separated by commas (or tabs)
Ozone,Solar.R,Wind,Temp,Month,Day
41,190,7.4,67,5,1
36,118,8,72,5,2
12,149,12.6,74,5,3
18,313,11.5,62,5,4
NA,NA,14.3,56,5,5
Use
ozone <- read.table("ozone.csv", header=TRUE, sep=",")
or
ozone <- read.csv("ozone.csv")
Syntax notes
• Functions can have optional arguments (sep wasn’t used the
first time). Use help(read.table) for a complete description
of the function and all the arguments.
• There’s more than one way to do it.
• NA is the code for missing data. Think of it as “Don’t
Know”. R handles it sensibly in computations: eg 1+NA,
NA & FALSE, NA & TRUE. You cannot test temp==NA (Is
temperature equal to some number I don’t know?), so there
is a function is.na().
Reading text data
Sometime the variable names aren’t included
1 0.2 115 90 1 3 68 42 yes
2 0.7 193 90 3 1 61 48 yes
3 0.2 58 90 1 3 63 40 yes
4 0.2 5 80 2 3 65 75 yes
5 0.2 8.5 90 1 2 64 30 yes
and you have to supply them
psa <- read.table("psa.txt", col.names=c("ptid","nadirpsa",
"pretxpsa", "ps","bss","grade","age",
"obstime","inrem"))
or
psa <- read.table("psa.txt")
names(psa) <- c("ptid","nadirpsa","pretxpsa", "ps",
"bss","grade","age","obstime","inrem"))
Syntax notes
• Assigning a single vector (or anything else) to a variable uses
the same syntax as assigning a whole data frame.
• c() is a function that makes a single vector from its
arguments.
• names is a function that accesses the variable names of a data
frame
• Some functions (such as names) can be used on the LHS of
an assignment.
Fixed-format data
Two functions read.fwf and read.fortran read fixed-format data.
i1.3<-read.fortran("sipp87x.dat",c("f1.0","f9.0",
"f2.0","f3.0", "4f1.0", "15f1.0",
"2f12.7", "f1.0","f2.0" "2f1.0",
"f2.0", "15f1.0", "15f2.0",
"15f1.0","4f2.0", "4f1.0","4f1.0",
"15f1.0","4f8.0","4f7.0","4f8.0",
"4f5.0","15f1.0"), col.names=i1.3names,
buffersize=200)
Here i1.3names is a vector of names we created earlier. buffersize
says how many lines to read in one gulp — small values can
reduce memory use
Other statistical packages
library(foreign)
stata <- read.dta("salary.dta")
spss <- read.spss("salary.sav", to.data.frame=TRUE)
sasxport <- read.xport("salary.xpt")
epiinfo <- read.epiinfo("salary.rec")
Notes:
• Many functions in R live in optional packages. The library()
function lists packages, shows help, or loads packages from
the package library.
• The foreign package is in the standard distribution. It handles
import and export of data. Hundreds of extra packages are
available at http://cran.us.r-project.org.
The web
Files for read.table can live on the web
fl2000<-read.table("http://faculty.washington.edu/tlumley/
data/FLvote.dat", header=TRUE)
It’s also possible to read from more complex web databases (such
as the genome databases)
Operating on data
As R can have more than one data frame available you need to
specify where to find a variable. The syntax antibiotics$duration
means the variable duration in the data frame antibiotics.
## This is a comment
## Convert temperature to real degrees
antibiotics$tempC <- (antibiotics$temp-32)*5/9
## display mean, quartiles of all variables
summary(antibiotics)
Subsets
Everything in R is a vector (but some have only one element).
Use [] to extract subsets
## First element
antibiotics$temp[1]
## All but first element
antibiotics$temp[-1]
## Elements 5 through 10
antibiotics$temp[5:10]
## Elements 5 and 7
antibiotics$temp[c(5,7)]
## People who received antibiotics (note ==)
antibiotics$temp[ antibiotics$antib==1 ]
## or
with(antibiotics, temp[antib==1])
Notes
• Positive indices select elements, negative indices drop ele-
ments
• 5:10 is the sequence from 5 to 10
• You need == to test equality, not just =
• with() temporarily sets up a data frame as the default place
to look up variables. You can do this longer-term with
attach(), but I don’t know any long-term R users who do
this. It isn’t as useful as it initial seems.
More subsets
For data frames you need two indices
## First row
antibiotics[1,]
## Second column
antibiotics[,2]
## Some rows and columns
antibiotics[3:7, 2:4]
## Columns by name
antibiotics[, c("id","temp","wbc")]
## People who received antibiotics
antibiotics[antibiotics$antib==1, ]
## Put this subset into a new data frame
yes <- antibiotics[antibiotics$antib==1,]
Computations
mean(antibiotics$temp)
median(antibiotics$temp)
var(antibiotics$temp)
sd(antibiotics$temp)
mean(yes$temp)
mean(antibiotics$temp[antibiotics$antib==1]
with(antibiotics, mean(temp[sex==2]))
toohot <- with(antibiotics, temp>99)
mean(toohot)
Factors
Factors represent categorical variables. You can’t do mathemat-
ical operations on them (except for ==)
> table(salary$rank,salary$field)
Arts Other Prof
Assist 668 2626 754
Assoc 1229 4229 1071
Full 942 6285 1984
> antibiotics$antib<-factor(antibiotics$antib,
labels=c("Yes","No"))
> antibiotics$agegp<-cut(antibiotics$antib, c(0,18,65,100))
> table(antibiotics$agegp)
(0,18] (18,65] (65,100]
2 19 4
Strings
Functions for searching and modifying strings are based on reg-
ular expressions, which are like simple programs for representing
strings
"a" matches the letter a
"TATAA" matches the string TATAA
"ACGT.C" matches ACGT followed by any single character,
followed by C
"a*b*" matches zero or more as followed by zero or more bs
"[A-Za-z]+" matches one or more characters between A and Z
or between a and z (in English, any letter).
"[[:alpha:]]+" matches one or more letters, defined according
to the current locale
".csv$" matches the string .csv at the end of a string
"([[:alpha:]]+)[[:space:][:punct:]]+1[[:space:][:punct:]]+"
matches any repeated word.
Functions for regular expressions
• grep(regexp, vector) finds all the strings in the vector that
contain a substring matching the regular expression
• sub(regexp, replacement, vector) replaces the first substring
matching the regular expression with the replacement (for
each element of the vector). gsub does the same thing but
can make more than one replacement per string
• regexpr(regexp, vector) returns the position of the first
match within each string, gregexpr is the same except that
it returns all matches.
• strsplit() splits a string at each match to a regular
expression
• glob2rx() converts filename wildcard specifications to regular
expressions
There is also support for Perl-style regular expressions with
similar functionality but different syntax
Help
• help(fn) for help on fn
• help.search("topic") for help pages related to ”topic
• apropos("tab") for functions whose names contain ”tab”
• Search function on the http://www.r-project.org web site.
Graphics
R (and S-PLUS) can produce graphics in many formats, includ-
ing:
• on screen
• PDF files for L
A
T
EX or emailing to people
• PNG or JPEG bitmap formats for web pages (or on non-
Windows platforms to produce graphics for MS Office). PNG
is also useful for graphs of large data sets.
• On Windows, metafiles for Word, Powerpoint, and similar
programs
Setup
Graphs should usually be designed on the screen and then may
be replotted on eg a PDF file (for Word/Powerpoint you can
just copy and paste)
For printed graphs, you will get better results if you design the
graph at the size it will end up, eg:
## on Windows
windows(height=4,width=6)
## on Unix
x11(height=4,width=6)
Word or L
A
T
EX can rescale the graph, but when the graph gets
smaller, so do the axis labels...
Finishing
After you have the right commands to draw the graph you can
produce it in another format: eg
## start a PDF file
pdf("picture.pdf",height=4,width=6)
## your drawing commands here
...
### close the PDF file
dev.off()
Drawing
Usually use plot() to create a graph and then lines(), points(),
legend(), text(), and other commands to annotate it.
plot() is a generic function: it does appropriate things for
different types of input
## scatterplot
plot(salary$year, salary$salary)
## boxplot
plot(salary$rank, salary$salary)
## stacked barplot
plot(salary$field, salary$rank)
and others for other types of input. This is done by magic
(actually, by advanced technology).
Formula interface
The plot() command can be written
plot(salary~rank, data=salary)
introducing the formula system that is also used for regression
models. The variables in the formula are automatically looked
up in the data= argument.
Designing graphs
Two important aspects of designing a graph
• It should have something to say
• It should be legible
Having something to say is your problem; software can help with
legibility.
Designing graphs
Important points
• Axes need labels (with units, large enough to read)
• Color can be very helpful (but not if the graph is going to
be printed in black and white).
• Different line or point styles usually should be labelled.
• Points plotted on top of each other won’t be seen
After these are satisfied, it can’t hurt to have the graph look
nice.
Options
Set up a data set: daily ozone concentrations in New York,
summer 1973
data(airquality)
names(airquality)
airquality$date<-with(airquality, ISOdate(1973,Month,Day))
All these graphs were designed at 4in×6in and stored as PDF
files
plot(Ozone~date, data=airquality)
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
0
50
100
150
date
Ozone
May Jun Jul Aug Sep Oct
plot(Ozone~date, data=airquality,type="l")
0
50
100
150
date
Ozone
May Jun Jul Aug Sep Oct
plot(Ozone~date, data=airquality,type="h")
0
50
100
150
date
Ozone
May Jun Jul Aug Sep Oct
plot(Ozone~date, data=airquality,type="n")
0
50
100
150
date
Ozone
May Jun Jul Aug Sep Oct
bad<-ifelse(airquality$Ozone>=90, "orange","forestgreen")
plot(Ozone~date, data=airquality,type="h",col=bad)
abline(h=90,lty=2,col="red")
0
50
100
150
date
Ozone
May Jun Jul Aug Sep Oct
Notes
• type= controls how data are plotted. type="n" is not as useless
as it looks: it can set up a plot for latter additions.
• Colors can be specified by name (the colors() function gives
all the names), by red/green/blue values (#rrggbb with six
base-sixteen digits) or by position in the standard palette of
8 colors. For pdf() and quartz(), partially transparent colors
can be specified by #rrggbbaa.
• abline draws a single straight line on a plot
• ifelse() selects between two vectors based on a logical
variable.
• lty specifies the line type: 1 is solid, 2 is dashed, 3 is dotted,
then it gets more complicated.
Adding to a plot
data(cars)
plot(speed~dist,data=cars)
with(cars, lines(lowess(dist,speed), col="tomato", lwd=2))
plot(speed~dist,data=cars, log="xy")
with(cars, lines(lowess(dist,speed), col="tomato", lwd=2))
with(cars, lines(supsmu(dist,speed), col="purple", lwd=2))
legend(2,25, legend=c("lowess","supersmoother"),bty="n", lwd=2,
col=c("tomato","purple"))
Adding to a plot
● ●
● ●
●
●
● ● ●
● ●
● ● ● ●
● ●
● ●
● ● ● ●
● ● ●
● ●
● ● ●
● ● ● ●
● ● ●
● ● ● ● ●
●
●
● ●
● ●
●
0 20 40 60 80 100 120
5
10
15
20
25
dist
speed
Adding to a plot
● ●
● ●
●
●
● ● ●
● ●
● ● ● ●
● ●
● ●
● ● ● ●
● ● ●
● ●
● ● ●
● ● ● ●
● ● ●
● ●●● ●
●
● ● ●
● ●
●
2 5 10 20 50 100
5
10
15
25
dist
speed
Adding to a plot
● ●
● ●
●
●
● ● ●
● ●
● ● ● ●
● ●
● ●
● ● ● ●
● ● ●
● ●
● ● ●
● ● ● ●
● ● ●
● ●●● ●
●
● ● ●
● ●
●
2 5 10 20 50 100
5
10
15
25
dist
speed
lowess
supersmoother
Notes
• lines adds lines to an existing plot (points() adds points).
• lowess() and supsmu() are scatterplot smoothers. They draw
smooth curves that fit the relationship between y and x
locally.
• log="xy" asks for both axes to be logarithm (log="x" would
just be the x-axis)
• legend() adds a legend
Boxplots
data(api, package="survey")
boxplot(mobility~stype,data=apipop, horizontal=TRUE)
Boxplots
●
● ●
● ●
● ●
● ●
●
●
● ●
●
●
●
●
● ●
●
● ●
● ●
● ●
● ●
●●
● ● ●
● ●
● ●
● ●
●
●
● ●
● ●
●
● ● ● ●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●●
● ●
● ● ●
●
●
●
● ●
●
● ●
●
● ●
●
●
●
● ●
●
● ● ●
●
●
●
● ●
●
● ● ●
●
●
●●● ●
●
● ●
●
● ●
●
● ●
● ● ●
● ●
●● ●
●
●
● ●
●●
●
●● ●
● ● ●
● ●
●
●
●
● ●
● ●
●
● ●
● ●
●
●
● ●
● ●
●
● ●
● ●
● ●
● ●
● ●
●
● ●
● ●
●
●
●
●
●
●● ●
● ●
● ● ●
● ● ● ●
●●
● ●
●● ● ●
●
● ● ●
●
●
● ●
●
●
●● ●
● ●
●●
● ● ●
●
● ●
●
●
● ●
●
● ●
●
●
● ●
● ● ●●
●
●
●
●
●●
● ● ● ●
● ● ●
●
● ● ●
●
●
●
● ●
●
●
● ● ●
● ● ●
● ●●
● ●
●
●
● ●
● ●
●
● ●
● ● ●
● ●
●
●●
● ●
● ●
●
E
H
M
0 20 40 60 80 100
% new to school
Level
Notes
• boxplot computes and draws boxplots.
• horizontal=TRUE turns a boxplot sideways
• xlab and ylab are general options for x and y axis labels.
Barplots
Use barplot to draw barplots and hist to draw histograms:
barplot(VADeaths,beside=TRUE,legend=TRUE)
hist(apipop$api99,col="peachpuff",xlab="1999 API",
main="",prob=TRUE)
• main= specifies a title for the top of the plot
• prob=TRUE asks for a real histogram with probability density
rather than counts.
Rural Male Rural Female Urban Male Urban Female
50−54
55−59
60−64
65−69
70−74
0
10
20
30
40
50
60
70
1999 API
Density
300 400 500 600 700 800 900 1000
0.0000
0.0010
0.0020
Scatterplot matrix and color-blindness
Shinobu Ishihara was a Japanese opthalmologist. While working
in the Military Medical School he was asked to devise a testing
system for color vision abnormalities. The original plates were
hand-painted and had hiragana symbols as the patterns, a later
‘international’ edition used arabic numerals.
We will examine the colors on one of these plates.
Getting the data
The first step is to get colors into R. I converted the JPEG file to
a PNG file, which can then be converted to a plain text format.
## read file in SNG format, converted via PNG from JPEG
disappearing<-readLines("ishihara-disappearing.sng")
start<-grep("IMAGE",disappearing)+2
end<-length(disappearing)+1
disappearing<-unlist(strsplit(disappearing[start:end],
"[[:space:]]"))
## remove very rare colors, which are just edge effects
disappearing<-names(table(disappearing))[table(disappearing)>6]
## change rrggbb to #RRGGBB
disappearing<-paste("#",toupper(disappearing),sep="")
Color spaces
The convertColor function converts between coordinate systems
for color (R 2.1.0-forthcoming). Here we
Lab.dis<-convertColor(matrix(disappearing), from=hexcolor,
to="Lab",scale.in=NULL)
The CIE Lab coordinate system is approximately perceptually
uniform, with orthogonal light:dark, red:green, and blue:yellow
axes.
Lab coordinates
Blue-green points are separated from the dark red points on the
b axis but not on a or L.
Since the b axis is supposed to be aligned with exactly the color
spectrum that is indistinguishable in red-green colorblindnesss,
this explains why the tests work.
Remapping
The dichromat package in R implements a mapping that shows
how colours appear to color-blind viewers.
We can look at the Lab space after the transformation for
protanopia
Protanopia
Image plots
image() plots colors to indicate values on a two-dimensional grid.
A red-green spectrum is often used to code the values (especially
in genomics) but this is a really bad idea.
Use the dichromat package to compare red:green and blue:yellow
spectra.
par(mfrow=c(2,3))
x<-matrix(rnorm(10*10),10)
redgreen<-colorRampPalette(c("red","green3"))
image(1:10,1:10,x, col=bluescale(10),
main="blue-yellow scale")
image(1:10,1:10,x, col=dichromat(bluescale(10)), main="deutan")
image(1:10,1:10,x,col=dichromat(bluescale(10),"protan"), main="protan")
image(1:10,1:10,x, col=redgreen(10),
main="red-green scale")
image(1:10,1:10,x, col=dichromat(redgreen(10)), main="deutan")
image(1:10,1:10,x, col=dichromat(redgreen(10),"protan"), main="protan")
Image plots
2 4 6 8 10
2
4
6
8
10
blue−yellow scale
1:10
2 4 6 8 10
2
4
6
8
10
deutan
1:10
1:10
2 4 6 8 10
2
4
6
8
10
protan
1:10
1:10
2 4 6 8 10
2
4
6
8
10
red−green scale
2 4 6 8 10
2
4
6
8
10
deutan
1:10
2 4 6 8 10
2
4
6
8
10
protan
1:10
Large data sets
Scatterplots quickly get crowded. For example, the California
Academic Performance Index is reported on 6194 schools
> plot(api00~api99,data=apipop)
> colors<-c("tomato","forestgreen","purple")[apipop$stype]
> plot(api00~api99,data=apipop,col=colors)
Large data sets
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ● ●
●
●
●
●
●
●
● ●
●
●
●
● ● ●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●●
●
●
●
● ●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
● ●
●
●
● ●
●
●
●
●
●
● ●
● ●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
● ●
●●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
● ●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●● ●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
● ●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●●
●
●
● ●
●
●
●
● ●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
300 400 500 600 700 800 900
400
500
600
700
800
900
api99
api00
Large data sets
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ● ●
●
●
●
●
●
●
● ●
●
●
●
● ● ●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●●
●
●
●
● ●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
● ●
●
●
● ●
●
●
●
●
●
● ●
● ●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
● ●
●●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
● ●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●● ●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
● ●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●●
●
●
● ●
●
●
●
● ●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
300 400 500 600 700 800 900
400
500
600
700
800
900
api99
api00
Density plots
For a single large scatterplot some form of density estimation is
useful
library(MASS)
with(apipop, image(kde2d(api99,api00),
col=grey(seq(1,0.2,length=20))))
library(hexbin)
with(apipop, plot(hexbin(api99,api00), style="centroids"))
• kde2d in the MASS package is a 2-dimensional kernel density
estimate. It returns the density of points everywhere on a
rectangular grid. Variants are contour, which draws contours
and filled.contour, which does coloring and contours.
• image draws images from a rectangular grid of data
Density plots
• hexbin is in the hexbin package from the Bioconductor
project. It computes the number of points in each hexagonal
bin.
• The style=centroids plot puts a filled hexagon with size
depending on the number of points at the centroid of the
points in the bin.
Density plots
300 400 500 600 700 800 900
400
500
600
700
800
900
Density plots
1
7
12
18
23
29
34
40
46
51
57
62
68
73
79
84
90
Counts
300 400 500 600 700 800 900
400
500
600
700
800
900
Smoothers
For showing multiple groups a scatterplot smoother or perhaps
boxplots would be better.
> boxplot(api00~cut(api99,(3:10)*100), data=apipop)
> par(las=1)
> par(mar=c(5.1,10.1,2.1,2.1))
> boxplot(api00~interaction(stype,
cut(api99,(3:10)*100)),
data=apipop, horizontal=TRUE,col=1:3)
plot(api00~api99,data=apipop,type="n")
with(subset(apipop, stype=="E"),
lines(lowess(api99, api00), col="tomato"))
with(subset(apipop, stype=="H"),
lines(lowess(api99, api00), col="forestgreen"))
with(subset(apipop, stype=="M"),
lines(lowess(api99, api00), col="purple"))
Smoothers
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
(300,400] (400,500] (500,600] (600,700] (700,800] (800,900] (900,1e+03]
400
500
600
700
800
900
Smoothers
● ● ●
● ●
●
●
● ● ●
●
●
●
●
● ●
●
● ●
● ●
●
●
●
●
E.(300,400]
H.(300,400]
M.(300,400]
E.(400,500]
H.(400,500]
M.(400,500]
E.(500,600]
H.(500,600]
M.(500,600]
E.(600,700]
H.(600,700]
M.(600,700]
E.(700,800]
H.(700,800]
M.(700,800]
E.(800,900]
H.(800,900]
M.(800,900]
E.(900,1e+03]
H.(900,1e+03]
M.(900,1e+03]
400 500 600 700 800 900
Smoothers
300 400 500 600 700 800 900
400
500
600
700
800
900
api99
api00
Notes
• cut turns a variable into a factor by cutting it at the specified
points.
• Note the use of type="n"
• par(mar=) sets the margins around the plot. We need a large
left margin for the labels.
• subset takes a subset of a data frame.
Example: Confidence intervals
A popular plot in the lab sciences looks like:
70−74 65−69 60−64 55−59 50−54
Rural Male
Rural Female
Urban Male
Urban Female
Death Rates in Virginia
0
20
40
60
80
100
and can be created with gplots::barplot2
Example: Confidence intervals
Line plots are ordinarily preferable to bar plots,
55 60 65 70
0
20
40
60
80
100
Age
Mortality
rate
(/1000py)
Rural Male
Rural Female
Urban Male
Urban Female
Example: Confidence intervals
but the confidence intervals get in the way
55 60 65 70
0
20
40
60
80
100
Age
Mortality
rate
(/1000py)
Rural Male
Rural Female
Urban Male
Urban Female
Example: Confidence intervals
Offsetting the intervals slightly and coloring them helps a bit
55 60 65 70
0
20
40
60
80
100
Age
Mortality
rate
(/1000py)
Rural Male
Rural Female
Urban Male
Urban Female
Example: Confidence intervals
We draw the confidence intervals with the segments() function.
A common strategy is to plot the error bars leading up from
upper curves and down from lower curves, but this is where they
are least useful.
Transparency is useful to allow overlap, but requires bands rather
than intervals
Only a few formats support transparent colors (eg PNG and
PDF) and software may not support it (R does only for PDF).
Colors are specified as RGBA, where the A or α channel is 1 for
completely opaque and 0 for completely transparent.
Example: Confidence intervals
55 60 65 70
0
20
40
60
80
Age
Mortality
rate
(/1000py)
Rural Male
Rural Female
Urban Male
Urban Female
Confidence intervals and even simultaneous confidence bands
do not necessarily reflect uncertainty in the shape of a curve
correctly.
For example, in a plot of heart disease risk vs blood pressure we
might see an increased risk for the lowest blood pressures and
want to know if this increase is real.
This requires simulating or bootstrapping realisations of the
curve to compare to the actual curve. Simulation is most useful
in a testing context, where we can generate curves under the
null hypothesis.
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
0 10 20 30 40 50
−20
0
20
40
60
80
x
y
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
0 10 20 30 40 50
−20
0
20
40
60
80
x
y
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
0 10 20 30 40 50
−20
0
20
40
60
80
x
y
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
0 10 20 30 40 50
−20
0
20
40
60
80
x
y
Code
pdf("uncertainty.pdf",height=6,width=7,version="1.4")
x<-runif(50)
y<-rnorm(50)+2*x
ii<-order(x)
x<-x[ii]
y<-y[ii]
ll<-lowess(x,y)
plot(x,y,ylim=c(-3,6))
lines(ll,col="red",lwd=2)
s<-sqrt(var(ll$y-y))
polygon(c(x,rev(x)), c(ll$y+2*s,rev(ll$y-2*s)),
col="#FF000070", border=NA)
plot(x,y,ylim=c(-3,6))
lines(ll,col="red",lwd=2)
replicate(10, {index<-sample(50,replace=TRUE);
lines(lowess(x[index],y[index]),col="grey")})
Code
plot(x,y,ylim=c(-3,6))
lines(ll,col="red",lwd=2)
replicate(10, {xindex<-sample(50,replace=TRUE);
yindex<-sample(50,replace=TRUE);
lines(lowess(x[xindex],y[yindex]),col="grey")})
dev.off()
Conditioning plots
Ozone is a secondary pollutant, it is produced from organic
compounds and atmostpheric oxygen in reactions catalyzed by
nitrogen oxides and powered by su nlight.
However, looking at ozone concentrations in NY in summer we
see a non-monotone relationship with sunlight
Conditioning plots
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
● ●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
0 50 100 150 200 250 300
0
50
100
150
Solar.R
Ozone
Conditioning plots
Here we draw a scatterplot of Ozone vs Solar.R for various
subranges of Temp and Wind. A simple version of what is possible
with the Trellis system.
data(airquality)
coplot(Ozone ~ Solar.R | Temp * Wind, number = c(4, 4),
data = airquality,
pch = 21, col = "goldenrod", bg = "goldenrod")
Conditioning plots
●
●
●
●
● ● ●
●
0
50
150
●
●
●
●
●
●
●
●
●
●
●
●
●
0 100 250
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
0 100 250
●
●
●
● ●
●
●●
●
● ●
● ● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●●
● ●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
● ●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
0
50
150
● ●
●
● ●
● ●
●
●
●
●●
●
●● ●●
● ●
● ●
●
●
●
●
●
●
0
50
150
● ●
●●
●
●
●
●
●
●●
●
●
● ●
● ●
●
●
●
●
●
●
● ●
●
●
●
●
● ●
●
●
●
●
●
●●
●
●
● ●
●
●
● ●
●
●
●
●
● ●
●
●
●
●
●
● ●
●
● ●
● ●
●
●
●
●
●
●
●
● ●
●
● ●
● ● ●
●
● ● ●
0 100 250
● ●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
● ● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
0 100 250
●
●
●
●
●
●
●
●
●
●
●
●
0
50
150
Solar.R
Ozone
60 70 80 90
Given : Temp
5
10
15
20
Given
:
Wind
Trellis
The best-known system for producing conditioning plots is
Cleveland’s Trellis, in S-PLUS. There is a similar system based
on Cleveland’s research in R, called lattice.
Trellis is not restricted to conditioning scatterplots: it allows
histograms, bo xplots, barcharts, and even 3-d plots.
One dramatic example of the usefulness of these plots is the
following graph of some repeatedly analyzed data on field trials
of barley varieties.
library(lattice)
data(barley)
dotplot(variety ~ yield | site, data = barley, groups = year,
key = simpleKey(levels(barley$year), space = "right"))
Dotplots: barley varieties
Barley Yield (bushels/acre)
20 30 40 50 60
Svansota
No. 462
Manchuria
No. 475
Velvet
Peatland
Glabron
No. 457
Wisconsin No. 38
Trebi
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
Grand Rapids
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
Duluth
Svansota
No. 462
Manchuria
No. 475
Velvet
Peatland
Glabron
No. 457
Wisconsin No. 38
Trebi
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
University Farm
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
Morris
Svansota
No. 462
Manchuria
No. 475
Velvet
Peatland
Glabron
No. 457
Wisconsin No. 38
Trebi
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
Crookston
20 30 40 50 60
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
Waseca
1932
1931
●
●
Syntax notes
Trellis graphics are specified by a formula:
response~predictor|conditioning*variables
The conditioning variables must be discrete or be shingles
produced with a function such as equal.count.
Some Trellis functions (eg histogram) do not have a response
variable, and some (eg cloud, levelplot) have more than one
predictor variable.
The panel function that draws each subplot can be customised
either by specifying options or by writing a new panel function.
Read Cleveland’s Visualizing Data for examples (and because
everyone producing statistical graphics should read it).
R FAQ 7.22
Why do lattice/trellis graphics not work?
The most likely reason is that you forgot to tell R to display
the graph. Lattice functions such as xyplot() create a graph
object, but do not display it (the same is true of Trellis graphics
in S-Plus). The print() method for the graph object produces
the actual display. When you use these functions interactively
at the command line, the result is automatically printed, but in
source() or inside your own functions you will need an explicit
print() statement.
Coplot: NY ozone
We can produce a conditioning plot of NY summer ozone with
the lattice package
xyplot(Ozone~Solar.R|equal.count(Temp,4)*equal.count(Wind,4),
data=airquality,
strip=strip.custom(var.name=c("Temperature","Wind speed")))
The labelling is slightly different from the coplot version
Coplot: NY ozone
Solar.R
Ozone
0
50
100
150
0 100 200 300
●
●
●
●
● ● ●
●
Temperature
Wind Speed
●
●
●
●
●
●
●
●
●
●
●
●
●
Temperature
Wind Speed
0 100 200 300
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
Temperature
Wind Speed
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
Temperature
Wind Speed
●
●
●
● ●
●
●●
●
● ●
● ● ●
● ●
●
●
●
●
Temperature
Wind Speed
●
●
●
●
●
●
●
●
●
●
● ●
●●
● ●
●
●
●
●
●
●
●
Temperature
Wind Speed
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
Temperature
Wind Speed
0
50
100
150
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
Temperature
Wind Speed
0
50
100
150
● ●
●
● ●
● ●
●●
●
●●
●
● ● ●● ● ●
● ●
● ●
●
●
●
●
Temperature
Wind Speed
● ●
●●
●
●
●
● ●
●●
●
●
● ●
● ●
●
●
●
●
Temperature
Wind Speed
●
●
● ●
●
●
●
●
● ●
●
●
●
● ●
●●
●
●
●
Temperature
Wind Speed
● ●
●
● ●
●
●
●
●
● ●
●
●
●
●
●
Temperature
Wind Speed
● ●
●
● ●
● ●
●
●
●
●
●
●
●
● ●
●
● ●
● ● ●
●
● ● ●
Temperature
Wind Speed
0 100 200 300
● ●
●
●
●
● ●
●
●
●
●●
● ●
●
●
●
● ● ●
Temperature
Wind Speed
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
Temperature
Wind Speed
0 100 200 300
0
50
100
150
●
●
●
●
●
●
●
●
●
●
●
●
Temperature
Wind Speed
Stereo pairs
As an example of more advanced things that can be done, here
is a pointless example of three-d graphics
par.set <-list(axis.line = list(col = "transparent"),
clip = list(panel = FALSE))
print(cloud(Sepal.Length ~ Petal.Length * Petal.Width,
data = iris, cex = .8,
groups = Species,
main = "Stereo",
screen = list(z = 20, x = -70, y = 3),
par.settings = par.set),
split = c(1,1,2,1), more = TRUE)
print(cloud(Sepal.Length ~ Petal.Length * Petal.Width,
data = iris, cex = .8,
groups = Species,
main = "Stereo",
screen = list(z = 20, x = -70, y = 0),
par.settings = par.set),
split = c(2,1,2,1))
Stereo pairs
Stereo
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ● ●
● ●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
Petal.Length
Petal.Width
Sepal.Length
Stereo
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
● ●
●
●
●
●
●
●
●
●●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
●
Petal.Length
Petal.Width
Sepal.Length
Mathematical annotation
An expression can be specified in R for any text in a graph
(help(plotmath) for details). Here we annotate a graph drawn
with polygon.
x<-seq(-10,10,length=400)
y1<-dnorm(x)
y2<-dnorm(x,m=3)
par(mar=c(5,4,2,1))
plot(x,y2,xlim=c(-3,8),type="n",
xlab=quote(Z==frac(mu[1]-mu[2],sigma/sqrt(n))),
ylab="Density")
polygon(c(1.96,1.96,x[240:400],10),
c(0,dnorm(1.96,m=3),y2[240:400],0),
col="grey80",lty=0)
lines(x,y2)
lines(x,y1)
polygon(c(-1.96,-1.96,x[161:1],-10),
c(0,dnorm(-1.96,m=0),y1[161:1],0),
col="grey30",lty=0)
polygon(c(1.96,1.96,x[240:400],10),
c(0,dnorm(1.96,m=0),y1[240:400],0),
col="grey30")
Mathematical annotation
legend(4.2,.4,fill=c("grey80","grey30"),
legend=expression(P(abs(Z)>1.96,H[1])==0.85,
P(abs(Z)>1.96,H[0])==0.05),bty="n")
text(0,.2,quote(H[0]:~~mu[1]==mu[2]))
text(3,.2,quote(H[1]:~~mu[1]==mu[2]+delta))
Mathematical annotation
−2 0 2 4 6 8
0.0
0.1
0.2
0.3
0.4
Z =
µ1 − µ2
σ n
Density
P(Z > 1.96, H1) = 0.85
P(Z > 1.96, H0) = 0.05
H0 : µ1 = µ2 H1 : µ1 = µ2 + δ
Managing code and data
Options for storage
• Workspace. When R starts it will read in the file .RData, and
when it exits you are given the chance to save the workspace
to that file (you can save it at any time with save.image()).
This saves everything except loaded packages and is the
equivalent of the .Data directory in S-PLUS.
• Binary files. The save() command puts specified functions
and data in a binary file. This file can be attach()ed (like a
directory in S-PLUS) or load()ed.
• Source code. Instead of saving results and data they can be
recreated as needed from source code.
Multiple projects
There are two extreme ways to handle multiple projects in R
• Store each project in a separate directory and use the .RData
file to hold everything. If you want to share functions or
objects with another project then explicitly export and import
them. The .RData file is primary; any transcripts or source
files are documentation.
• Store everything as source code. For every piece of analysis
have a file that reads in data, processes it, and possibly saves
a modified version to a new file. The source is primary, any
saved files are just a labour-saving device.
The same choices apply to programming as well as data analysis,
and to other dialects of S.
Workspace is primary
The first method is common among new users of S-PLUS, partly
because S-PLUS automatically saves your workspace. Many of
us subsequently find that we aren’t sufficiently organised to be
sure that we keep records of how every analysis was done.
This approach is (even) riskier in R than in S-PLUS.
• In R the workspace is only saved when you explicitly ask for
it; in S-PLUS it is saved frequently
• In R a corrupted .RData is likely to be completely unreadable,
in S-PLUS many objects will still be recoverable.
It makes sense for short-term projects, especially if data loss is
not critical, or for very careful people.
Source is primary
Managing projects is easy when everything can be reconstructed
from source files. These files and intermediate data files can be
stored in a project directory where they are easy to find and are
automatically time-stamped by the operating system.
Emacs Speaks Statistics (ESS) is particularly useful for this style
of R use. With R running in an Emacs window you can run
sections of code with a few keystrokes. The S-PLUS script
window also offers many of the features of ESS.
Logging
One problem with interactive data analysis is keeping a good
log of your analysis. This problem can be avoided by using
interactive analysis only to construct a script that is then run to
provide the final results.
Other options:
• ESS will capture a complete transcript, as will the Windows
or Mac GUIs and the JGR GUI
• in R, sink(filename, split=TRUE) will send all output to both
filename and the screen. Use sink() before quitting to close
the file.
Note that none of these will log graphics output.
Merging and matching
The data for an analysis often do not come in a single file.
Combining multiple files is necessary.
If two data sets have the same individuals in the same order,
they can simply be pasted together side by side.
## CHS baseline data
baseline <- read.spss("I:/DISTRIB/BASEBOTH.SAV", to.data.frame=TRUE)
## Events data (eg death, heart attack, ...)
events <- read.spss("I:/SAVEFILES/EVSUM04.SAV", to.data.frame=TRUE)
if (!all(baseline$IDNO==events$IDNO)) {
stop("PANIC: They don’t match!")
} else {
alldata <- cbind(baseline, events[,c("TTODTH","DEATH",
"TTOMI","INCMI")])
}
Merging: order
The data might need to be sorted first
index1 <- order(baseline$IDNO)
baseline <- baseline[index1,]
index2 <- order(events$IDNO)
events <- events[index2,]
if (!all(baseline$IDNO==events$IDNO)) {
stop("PANIC: They still don’t match!")
} else {
alldata <- cbind(baseline, events[,c("TTODTH","DEATH",
"TTOMI","INCMI")])
}
Note that order(baseline$IDNO) gives a subset of row numbers
containing all the rows but in a different (increasing) order.
Merging: merge
Or there might be different rows in the two data sets
• Some people are missing from one or other data set (eg
baseline and year 5 visits)
• Some people have multiple records in one data set (eg
baseline data and all hospitalisations
The merge function can do an database outer join, giving a data
set that has all the possible matches between a row in one and
a row in the other
Merging: merge
combined <- merge(baseline, hospvisits, by="IDNO", all=TRUE)
• by=IDNO says that the IDNO variable indicates individuals who
should be matched.
• all=TRUE says that even people with no records in the
hospvisits data set should be kept in the merged version.
How does it work: match
You could imagine a dumb algorithm for merging
for(row in firstdataset){
for(otherrow in seconddataset){
if (row$IDNO==otherrow$IDNO)
##add the row to the result
}
}
More efficiently, the match function gives indices to match one
variable to another
> match(c("B","I","O","S","T","A","T"),LETTERS)
[1] 2 9 15 19 20 1 20
> letters[match(c("B","I","O","S","T","A","T"),LETTERS)]
[1] "b" "i" "o" "s" "t" "a" "t"
Reshaping
Sometimes data sets are the wrong shape. Data with multiple
observations of similar quantities can be in long form (multiple
records per person) or wide form (multiple variables per person).
Example: The SeattleSNPs genetic variation discovery resource
supplies data in a format
SNP sample al1 al2
000095 D001 C T
000095 D002 T T
000095 D003 T T
so that data for a single person is broken across many lines. To
convert this to one line per person
> data<-read.table("http://pga.gs.washington.edu/data/il6
/ilkn6.prettybase.txt",
col.names=c("SNP","sample","allele1","allele2"))
> dim(data)
[1] 2303 4
> wideData<-reshape(data, direction="wide", idvar="sample",
timevar="SNP")
> dim(wideData)
[1] 47 99
> names(wideData)
[1] "sample" "allele1.95" "allele2.95" "allele1.205"
[5] "allele2.205" "allele1.276" "allele2.276" "allele1.321"
[9] "allele2.321" "allele1.657" "allele2.657" "allele1.1086"
...
• direction="wide" says we are going from long to wide format
• idvar="sample" says that sample identifies the rows in wide
format
• timevar="SNP" says that SNP identifies which rows go into
the same column in wide form (for repeated measurements
over time it would be the time variable)
Broken down by age and sex
A common request for Table 1 or Table 2 in a medical paper
is to compute means and standard deviations, percentages, or
frequency tables of many variables broken down by groups (eg
case/control status, age and sex, exposure,...).
That is, we need to apply a simple computation to subsets of
the data, and apply it to many variables. One useful function
is by(), another is tapply(), which is very similar (but harder to
remember).
> by(airquality$Ozone, list(month=airquality$Month),
mean, na.rm=TRUE)
month: 5
[1] 23.61538
------------------------------------------------------
month: 6
[1] 29.44444
------------------------------------------------------
month: 7
[1] 59.11538
------------------------------------------------------
month: 8
[1] 59.96154
------------------------------------------------------
month: 9
[1] 31.44828
Notes
• The first argument is the variable to be analyzed.
• The second argument is a list of variable defining sub-
sets. In this case, a single variable, but we could do
list(month=airquality$Month, toohot=airquality$Temp>85) to
get a breakdown by month and temperature
• The third argument is the analysis function to use on each
subset
• Any other arguments (na.rm=TRUE) are also given to the
analysis function
• The result is really a vector (with a single grouping variable)
or array (with multiple grouping variables). It prints differ-
ently.
Confusing digression: str()
How do I know it is an array? Because str() summarises the
internal structure of a variable.
> a<- by(airquality$Ozone, list(month=airquality$Month,
toohot=airquality$Temp>85),
mean, na.rm=TRUE)
> str(a)
by [1:5, 1:2] 23.6 22.1 49.3 40.9 22.0 ...
- attr(*, "dimnames")=List of 2
..$ month : chr [1:5] "5" "6" "7" "8" ...
..$ toohot: chr [1:2] "FALSE" "TRUE"
- attr(*, "call")= language by.data.frame(data =
as.data.frame(data), INDICES = INDICES,
FUN = FUN, na.rm = TRUE)
- attr(*, "class")= chr "by"
One function, many variables
There is a general function, apply() for doing something to rows
or columns of a matrix (or slices of a higher-dimensional array).
> apply(psa[,1:8],2,mean,na.rm=TRUE)
id nadir pretx ps bss grade
25.500000 16.360000 670.751163 80.833333 2.520833 2.146341
grade age obstime
2.146341 67.440000 28.460000
In this case there is a special, faster, function colMeans, but the
apply can be used with other functions such as sd, IQR, min,...
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf
e_lumley.pdf

More Related Content

Similar to e_lumley.pdf

Mixed Effects Models - Descriptive Statistics
Mixed Effects Models - Descriptive StatisticsMixed Effects Models - Descriptive Statistics
Mixed Effects Models - Descriptive StatisticsScott Fraundorf
 
Unit I - introduction to r language 2.pptx
Unit I - introduction to r language 2.pptxUnit I - introduction to r language 2.pptx
Unit I - introduction to r language 2.pptxSreeLaya9
 
Mapreduce Algorithms
Mapreduce AlgorithmsMapreduce Algorithms
Mapreduce AlgorithmsAmund Tveit
 
R-programming-training-in-mumbai
R-programming-training-in-mumbaiR-programming-training-in-mumbai
R-programming-training-in-mumbaiUnmesh Baile
 
Import and Export Big Data using R Studio
Import and Export Big Data using R StudioImport and Export Big Data using R Studio
Import and Export Big Data using R StudioRupak Roy
 
PPT ON MACHINE LEARNING by Ragini Ratre
PPT ON MACHINE LEARNING by Ragini RatrePPT ON MACHINE LEARNING by Ragini Ratre
PPT ON MACHINE LEARNING by Ragini RatreRaginiRatre
 
2015-10-23_wim_davis_r_slides.pptx on consumer
2015-10-23_wim_davis_r_slides.pptx on consumer2015-10-23_wim_davis_r_slides.pptx on consumer
2015-10-23_wim_davis_r_slides.pptx on consumertirlukachaitanya
 
R - Get Started I - Sanaitics
R - Get Started I - SanaiticsR - Get Started I - Sanaitics
R - Get Started I - SanaiticsVijith Nair
 
R programming slides
R  programming slidesR  programming slides
R programming slidesPankaj Saini
 
Lecture1_R.pdf
Lecture1_R.pdfLecture1_R.pdf
Lecture1_R.pdfBusyBird2
 

Similar to e_lumley.pdf (20)

Mixed Effects Models - Descriptive Statistics
Mixed Effects Models - Descriptive StatisticsMixed Effects Models - Descriptive Statistics
Mixed Effects Models - Descriptive Statistics
 
Unit I - introduction to r language 2.pptx
Unit I - introduction to r language 2.pptxUnit I - introduction to r language 2.pptx
Unit I - introduction to r language 2.pptx
 
Mapreduce Algorithms
Mapreduce AlgorithmsMapreduce Algorithms
Mapreduce Algorithms
 
R-programming-training-in-mumbai
R-programming-training-in-mumbaiR-programming-training-in-mumbai
R-programming-training-in-mumbai
 
INTRODUCTION TO STATA.pptx
INTRODUCTION TO STATA.pptxINTRODUCTION TO STATA.pptx
INTRODUCTION TO STATA.pptx
 
Import and Export Big Data using R Studio
Import and Export Big Data using R StudioImport and Export Big Data using R Studio
Import and Export Big Data using R Studio
 
PPT ON MACHINE LEARNING by Ragini Ratre
PPT ON MACHINE LEARNING by Ragini RatrePPT ON MACHINE LEARNING by Ragini Ratre
PPT ON MACHINE LEARNING by Ragini Ratre
 
R training
R trainingR training
R training
 
2015-10-23_wim_davis_r_slides.pptx on consumer
2015-10-23_wim_davis_r_slides.pptx on consumer2015-10-23_wim_davis_r_slides.pptx on consumer
2015-10-23_wim_davis_r_slides.pptx on consumer
 
R - Get Started I - Sanaitics
R - Get Started I - SanaiticsR - Get Started I - Sanaitics
R - Get Started I - Sanaitics
 
R programming slides
R  programming slidesR  programming slides
R programming slides
 
Python basics
Python basicsPython basics
Python basics
 
Python basics
Python basicsPython basics
Python basics
 
Python basics
Python basicsPython basics
Python basics
 
Python basics
Python basicsPython basics
Python basics
 
Python basics
Python basicsPython basics
Python basics
 
Python basics
Python basicsPython basics
Python basics
 
Python basics
Python basicsPython basics
Python basics
 
Lecture1_R.pdf
Lecture1_R.pdfLecture1_R.pdf
Lecture1_R.pdf
 
Bt0065
Bt0065Bt0065
Bt0065
 

Recently uploaded

꧁❤ Greater Noida Call Girls Delhi ❤꧂ 9711199171 ☎️ Hard And Sexy Vip Call
꧁❤ Greater Noida Call Girls Delhi ❤꧂ 9711199171 ☎️ Hard And Sexy Vip Call꧁❤ Greater Noida Call Girls Delhi ❤꧂ 9711199171 ☎️ Hard And Sexy Vip Call
꧁❤ Greater Noida Call Girls Delhi ❤꧂ 9711199171 ☎️ Hard And Sexy Vip Callshivangimorya083
 
代办国外大学文凭《原版美国UCLA文凭证书》加州大学洛杉矶分校毕业证制作成绩单修改
代办国外大学文凭《原版美国UCLA文凭证书》加州大学洛杉矶分校毕业证制作成绩单修改代办国外大学文凭《原版美国UCLA文凭证书》加州大学洛杉矶分校毕业证制作成绩单修改
代办国外大学文凭《原版美国UCLA文凭证书》加州大学洛杉矶分校毕业证制作成绩单修改atducpo
 
Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...
Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...
Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...Jack DiGiovanna
 
Market Analysis in the 5 Largest Economic Countries in Southeast Asia.pdf
Market Analysis in the 5 Largest Economic Countries in Southeast Asia.pdfMarket Analysis in the 5 Largest Economic Countries in Southeast Asia.pdf
Market Analysis in the 5 Largest Economic Countries in Southeast Asia.pdfRachmat Ramadhan H
 
Data Warehouse , Data Cube Computation
Data Warehouse   , Data Cube ComputationData Warehouse   , Data Cube Computation
Data Warehouse , Data Cube Computationsit20ad004
 
VIP High Class Call Girls Bikaner Anushka 8250192130 Independent Escort Servi...
VIP High Class Call Girls Bikaner Anushka 8250192130 Independent Escort Servi...VIP High Class Call Girls Bikaner Anushka 8250192130 Independent Escort Servi...
VIP High Class Call Girls Bikaner Anushka 8250192130 Independent Escort Servi...Suhani Kapoor
 
Delhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip CallDelhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Callshivangimorya083
 
04242024_CCC TUG_Joins and Relationships
04242024_CCC TUG_Joins and Relationships04242024_CCC TUG_Joins and Relationships
04242024_CCC TUG_Joins and Relationshipsccctableauusergroup
 
Dubai Call Girls Wifey O52&786472 Call Girls Dubai
Dubai Call Girls Wifey O52&786472 Call Girls DubaiDubai Call Girls Wifey O52&786472 Call Girls Dubai
Dubai Call Girls Wifey O52&786472 Call Girls Dubaihf8803863
 
(PARI) Call Girls Wanowrie ( 7001035870 ) HI-Fi Pune Escorts Service
(PARI) Call Girls Wanowrie ( 7001035870 ) HI-Fi Pune Escorts Service(PARI) Call Girls Wanowrie ( 7001035870 ) HI-Fi Pune Escorts Service
(PARI) Call Girls Wanowrie ( 7001035870 ) HI-Fi Pune Escorts Serviceranjana rawat
 
High Class Call Girls Noida Sector 39 Aarushi 🔝8264348440🔝 Independent Escort...
High Class Call Girls Noida Sector 39 Aarushi 🔝8264348440🔝 Independent Escort...High Class Call Girls Noida Sector 39 Aarushi 🔝8264348440🔝 Independent Escort...
High Class Call Girls Noida Sector 39 Aarushi 🔝8264348440🔝 Independent Escort...soniya singh
 
Full night 🥵 Call Girls Delhi New Friends Colony {9711199171} Sanya Reddy ✌️o...
Full night 🥵 Call Girls Delhi New Friends Colony {9711199171} Sanya Reddy ✌️o...Full night 🥵 Call Girls Delhi New Friends Colony {9711199171} Sanya Reddy ✌️o...
Full night 🥵 Call Girls Delhi New Friends Colony {9711199171} Sanya Reddy ✌️o...shivangimorya083
 
Low Rate Call Girls Bhilai Anika 8250192130 Independent Escort Service Bhilai
Low Rate Call Girls Bhilai Anika 8250192130 Independent Escort Service BhilaiLow Rate Call Girls Bhilai Anika 8250192130 Independent Escort Service Bhilai
Low Rate Call Girls Bhilai Anika 8250192130 Independent Escort Service BhilaiSuhani Kapoor
 
Call Girls In Noida City Center Metro 24/7✡️9711147426✡️ Escorts Service
Call Girls In Noida City Center Metro 24/7✡️9711147426✡️ Escorts ServiceCall Girls In Noida City Center Metro 24/7✡️9711147426✡️ Escorts Service
Call Girls In Noida City Center Metro 24/7✡️9711147426✡️ Escorts Servicejennyeacort
 
EMERCE - 2024 - AMSTERDAM - CROSS-PLATFORM TRACKING WITH GOOGLE ANALYTICS.pptx
EMERCE - 2024 - AMSTERDAM - CROSS-PLATFORM  TRACKING WITH GOOGLE ANALYTICS.pptxEMERCE - 2024 - AMSTERDAM - CROSS-PLATFORM  TRACKING WITH GOOGLE ANALYTICS.pptx
EMERCE - 2024 - AMSTERDAM - CROSS-PLATFORM TRACKING WITH GOOGLE ANALYTICS.pptxthyngster
 
PKS-TGC-1084-630 - Stage 1 Proposal.pptx
PKS-TGC-1084-630 - Stage 1 Proposal.pptxPKS-TGC-1084-630 - Stage 1 Proposal.pptx
PKS-TGC-1084-630 - Stage 1 Proposal.pptxPramod Kumar Srivastava
 
dokumen.tips_chapter-4-transient-heat-conduction-mehmet-kanoglu.ppt
dokumen.tips_chapter-4-transient-heat-conduction-mehmet-kanoglu.pptdokumen.tips_chapter-4-transient-heat-conduction-mehmet-kanoglu.ppt
dokumen.tips_chapter-4-transient-heat-conduction-mehmet-kanoglu.pptSonatrach
 
Data Science Jobs and Salaries Analysis.pptx
Data Science Jobs and Salaries Analysis.pptxData Science Jobs and Salaries Analysis.pptx
Data Science Jobs and Salaries Analysis.pptxFurkanTasci3
 
Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip CallDelhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Callshivangimorya083
 

Recently uploaded (20)

꧁❤ Greater Noida Call Girls Delhi ❤꧂ 9711199171 ☎️ Hard And Sexy Vip Call
꧁❤ Greater Noida Call Girls Delhi ❤꧂ 9711199171 ☎️ Hard And Sexy Vip Call꧁❤ Greater Noida Call Girls Delhi ❤꧂ 9711199171 ☎️ Hard And Sexy Vip Call
꧁❤ Greater Noida Call Girls Delhi ❤꧂ 9711199171 ☎️ Hard And Sexy Vip Call
 
代办国外大学文凭《原版美国UCLA文凭证书》加州大学洛杉矶分校毕业证制作成绩单修改
代办国外大学文凭《原版美国UCLA文凭证书》加州大学洛杉矶分校毕业证制作成绩单修改代办国外大学文凭《原版美国UCLA文凭证书》加州大学洛杉矶分校毕业证制作成绩单修改
代办国外大学文凭《原版美国UCLA文凭证书》加州大学洛杉矶分校毕业证制作成绩单修改
 
Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...
Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...
Building on a FAIRly Strong Foundation to Connect Academic Research to Transl...
 
Market Analysis in the 5 Largest Economic Countries in Southeast Asia.pdf
Market Analysis in the 5 Largest Economic Countries in Southeast Asia.pdfMarket Analysis in the 5 Largest Economic Countries in Southeast Asia.pdf
Market Analysis in the 5 Largest Economic Countries in Southeast Asia.pdf
 
Delhi 99530 vip 56974 Genuine Escort Service Call Girls in Kishangarh
Delhi 99530 vip 56974 Genuine Escort Service Call Girls in  KishangarhDelhi 99530 vip 56974 Genuine Escort Service Call Girls in  Kishangarh
Delhi 99530 vip 56974 Genuine Escort Service Call Girls in Kishangarh
 
Data Warehouse , Data Cube Computation
Data Warehouse   , Data Cube ComputationData Warehouse   , Data Cube Computation
Data Warehouse , Data Cube Computation
 
VIP High Class Call Girls Bikaner Anushka 8250192130 Independent Escort Servi...
VIP High Class Call Girls Bikaner Anushka 8250192130 Independent Escort Servi...VIP High Class Call Girls Bikaner Anushka 8250192130 Independent Escort Servi...
VIP High Class Call Girls Bikaner Anushka 8250192130 Independent Escort Servi...
 
Delhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip CallDelhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls CP 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
 
04242024_CCC TUG_Joins and Relationships
04242024_CCC TUG_Joins and Relationships04242024_CCC TUG_Joins and Relationships
04242024_CCC TUG_Joins and Relationships
 
Dubai Call Girls Wifey O52&786472 Call Girls Dubai
Dubai Call Girls Wifey O52&786472 Call Girls DubaiDubai Call Girls Wifey O52&786472 Call Girls Dubai
Dubai Call Girls Wifey O52&786472 Call Girls Dubai
 
(PARI) Call Girls Wanowrie ( 7001035870 ) HI-Fi Pune Escorts Service
(PARI) Call Girls Wanowrie ( 7001035870 ) HI-Fi Pune Escorts Service(PARI) Call Girls Wanowrie ( 7001035870 ) HI-Fi Pune Escorts Service
(PARI) Call Girls Wanowrie ( 7001035870 ) HI-Fi Pune Escorts Service
 
High Class Call Girls Noida Sector 39 Aarushi 🔝8264348440🔝 Independent Escort...
High Class Call Girls Noida Sector 39 Aarushi 🔝8264348440🔝 Independent Escort...High Class Call Girls Noida Sector 39 Aarushi 🔝8264348440🔝 Independent Escort...
High Class Call Girls Noida Sector 39 Aarushi 🔝8264348440🔝 Independent Escort...
 
Full night 🥵 Call Girls Delhi New Friends Colony {9711199171} Sanya Reddy ✌️o...
Full night 🥵 Call Girls Delhi New Friends Colony {9711199171} Sanya Reddy ✌️o...Full night 🥵 Call Girls Delhi New Friends Colony {9711199171} Sanya Reddy ✌️o...
Full night 🥵 Call Girls Delhi New Friends Colony {9711199171} Sanya Reddy ✌️o...
 
Low Rate Call Girls Bhilai Anika 8250192130 Independent Escort Service Bhilai
Low Rate Call Girls Bhilai Anika 8250192130 Independent Escort Service BhilaiLow Rate Call Girls Bhilai Anika 8250192130 Independent Escort Service Bhilai
Low Rate Call Girls Bhilai Anika 8250192130 Independent Escort Service Bhilai
 
Call Girls In Noida City Center Metro 24/7✡️9711147426✡️ Escorts Service
Call Girls In Noida City Center Metro 24/7✡️9711147426✡️ Escorts ServiceCall Girls In Noida City Center Metro 24/7✡️9711147426✡️ Escorts Service
Call Girls In Noida City Center Metro 24/7✡️9711147426✡️ Escorts Service
 
EMERCE - 2024 - AMSTERDAM - CROSS-PLATFORM TRACKING WITH GOOGLE ANALYTICS.pptx
EMERCE - 2024 - AMSTERDAM - CROSS-PLATFORM  TRACKING WITH GOOGLE ANALYTICS.pptxEMERCE - 2024 - AMSTERDAM - CROSS-PLATFORM  TRACKING WITH GOOGLE ANALYTICS.pptx
EMERCE - 2024 - AMSTERDAM - CROSS-PLATFORM TRACKING WITH GOOGLE ANALYTICS.pptx
 
PKS-TGC-1084-630 - Stage 1 Proposal.pptx
PKS-TGC-1084-630 - Stage 1 Proposal.pptxPKS-TGC-1084-630 - Stage 1 Proposal.pptx
PKS-TGC-1084-630 - Stage 1 Proposal.pptx
 
dokumen.tips_chapter-4-transient-heat-conduction-mehmet-kanoglu.ppt
dokumen.tips_chapter-4-transient-heat-conduction-mehmet-kanoglu.pptdokumen.tips_chapter-4-transient-heat-conduction-mehmet-kanoglu.ppt
dokumen.tips_chapter-4-transient-heat-conduction-mehmet-kanoglu.ppt
 
Data Science Jobs and Salaries Analysis.pptx
Data Science Jobs and Salaries Analysis.pptxData Science Jobs and Salaries Analysis.pptx
Data Science Jobs and Salaries Analysis.pptx
 
Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip CallDelhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
 

e_lumley.pdf

  • 1. R Fundamentals and Programming Techniques Thomas Lumley R Core Development Team and UW Dept of Biostatistics Birmingham — 2006–2–27/28
  • 2. What are R and S-PLUS? • R is a free implementation of a dialect of the S language, the statistics and graphics environment for which John Chambers won the ACM Software Systems award. S was consciously designed to blur the distinction between users and programmers. S-PLUS is a commercial system (Insightful Co) based on Bell Labs’ S. • S is a system for interactive data analysis. It has always been designed with interactive use in mind. • S is a high-level programming language, with similarities to Scheme and Python. It is a good system for rapid development of statistical applications. For example, the survey package was developed by one person, part time, and is about 1.5% the size of the Census Bureau’s VPLX package (which does less).
  • 3. Why not S? R (and S) are accused of being slow, memory-hungry, and able to handle only small data sets. This is completely true. Fortunately, computers are fast and have lots of memory. Data sets with a few tens of thousands of observations can be handled in 256Mb of memory, and quite large data sets with 1Gb of memory. Workstations with 32Gb or more to handle millions of observations are still expensive (but in a few years Moore’s Law should catch up). Tools for interfacing R with databases allow very large data sets, but this isn’t transparent to the user.
  • 4. Why not R? 21 CFR 11, Basel 2, and similar regulatory guidelines require tedious effort to document and verify things. Doing this for another system is unappealing (although not intrinsically harder than for commercial software) R has no GUI and no commercial hand-holding services. S-PLUS does. S-PLUS also has a number of specialised add-ons (I would buy S-PLUS just to run S+SeqTrial if I were designing clinical trials).
  • 5. How similar are R and S-PLUS? • For basic command-line data analysis they are very similar • Most programs written in one dialect can be translated straightforwardly to the other • Most large programs will need some translation • R has a very successful package system for distributing code and data.
  • 6. R GUIs Not GUIs for statistics, but for files/scripts/windows etc • built-in: Windows, Mac • cross-platform: JGR (http://www.rosudo.org/JGR), Emacs/ESS (http://ess.r-projet.org).
  • 7. Outline • Reading data • Simple data summaries • Graphics • Scripts, Transcripts, ESS. • Stratified data summaries • Sweave • More on functions (example: bootstrap) • Debugging and optimization • A little on objects • Regression models: lm, glm, coxph • Packages
  • 8. Reading data • Text files • Stata datasets • Web pages • (Databases) Much more information is in the Data Import/Export manual.
  • 9. Reading text data The easiest format has variable names in the first row case id gender deg yrdeg field startyr year rank admin 1 1 F Other 92 Other 95 95 Assist 0 2 2 M Other 91 Other 94 94 Assist 0 3 2 M Other 91 Other 94 95 Assist 0 4 4 M PhD 96 Other 95 95 Assist 0 and fields separated by spaces. In R, use salary <- read.table("salary.txt", header=TRUE) to read the data from the file salary.txt into the data frame salary.
  • 10. Syntax notes • Spaces in commands don’t matter (except for readability), but Capitalisation Does Matter. • TRUE (and FALSE) are logical constants • Unlike many systems, R does not distinguish between com- mands that do something and commands that compute a value. Everything is a function: ie returns a value. • Arguments to functions can be named (header=TRUE) or unnamed ("salary.txt") • A whole data set (called a data frame is stored in a variable (salary), so more than one dataset can be available at the same time.
  • 11. Reading text data Sometimes columns are separated by commas (or tabs) Ozone,Solar.R,Wind,Temp,Month,Day 41,190,7.4,67,5,1 36,118,8,72,5,2 12,149,12.6,74,5,3 18,313,11.5,62,5,4 NA,NA,14.3,56,5,5 Use ozone <- read.table("ozone.csv", header=TRUE, sep=",") or ozone <- read.csv("ozone.csv")
  • 12. Syntax notes • Functions can have optional arguments (sep wasn’t used the first time). Use help(read.table) for a complete description of the function and all the arguments. • There’s more than one way to do it. • NA is the code for missing data. Think of it as “Don’t Know”. R handles it sensibly in computations: eg 1+NA, NA & FALSE, NA & TRUE. You cannot test temp==NA (Is temperature equal to some number I don’t know?), so there is a function is.na().
  • 13. Reading text data Sometime the variable names aren’t included 1 0.2 115 90 1 3 68 42 yes 2 0.7 193 90 3 1 61 48 yes 3 0.2 58 90 1 3 63 40 yes 4 0.2 5 80 2 3 65 75 yes 5 0.2 8.5 90 1 2 64 30 yes and you have to supply them psa <- read.table("psa.txt", col.names=c("ptid","nadirpsa", "pretxpsa", "ps","bss","grade","age", "obstime","inrem")) or psa <- read.table("psa.txt") names(psa) <- c("ptid","nadirpsa","pretxpsa", "ps", "bss","grade","age","obstime","inrem"))
  • 14. Syntax notes • Assigning a single vector (or anything else) to a variable uses the same syntax as assigning a whole data frame. • c() is a function that makes a single vector from its arguments. • names is a function that accesses the variable names of a data frame • Some functions (such as names) can be used on the LHS of an assignment.
  • 15. Fixed-format data Two functions read.fwf and read.fortran read fixed-format data. i1.3<-read.fortran("sipp87x.dat",c("f1.0","f9.0", "f2.0","f3.0", "4f1.0", "15f1.0", "2f12.7", "f1.0","f2.0" "2f1.0", "f2.0", "15f1.0", "15f2.0", "15f1.0","4f2.0", "4f1.0","4f1.0", "15f1.0","4f8.0","4f7.0","4f8.0", "4f5.0","15f1.0"), col.names=i1.3names, buffersize=200) Here i1.3names is a vector of names we created earlier. buffersize says how many lines to read in one gulp — small values can reduce memory use
  • 16. Other statistical packages library(foreign) stata <- read.dta("salary.dta") spss <- read.spss("salary.sav", to.data.frame=TRUE) sasxport <- read.xport("salary.xpt") epiinfo <- read.epiinfo("salary.rec") Notes: • Many functions in R live in optional packages. The library() function lists packages, shows help, or loads packages from the package library. • The foreign package is in the standard distribution. It handles import and export of data. Hundreds of extra packages are available at http://cran.us.r-project.org.
  • 17. The web Files for read.table can live on the web fl2000<-read.table("http://faculty.washington.edu/tlumley/ data/FLvote.dat", header=TRUE) It’s also possible to read from more complex web databases (such as the genome databases)
  • 18. Operating on data As R can have more than one data frame available you need to specify where to find a variable. The syntax antibiotics$duration means the variable duration in the data frame antibiotics. ## This is a comment ## Convert temperature to real degrees antibiotics$tempC <- (antibiotics$temp-32)*5/9 ## display mean, quartiles of all variables summary(antibiotics)
  • 19. Subsets Everything in R is a vector (but some have only one element). Use [] to extract subsets ## First element antibiotics$temp[1] ## All but first element antibiotics$temp[-1] ## Elements 5 through 10 antibiotics$temp[5:10] ## Elements 5 and 7 antibiotics$temp[c(5,7)] ## People who received antibiotics (note ==) antibiotics$temp[ antibiotics$antib==1 ] ## or with(antibiotics, temp[antib==1])
  • 20. Notes • Positive indices select elements, negative indices drop ele- ments • 5:10 is the sequence from 5 to 10 • You need == to test equality, not just = • with() temporarily sets up a data frame as the default place to look up variables. You can do this longer-term with attach(), but I don’t know any long-term R users who do this. It isn’t as useful as it initial seems.
  • 21. More subsets For data frames you need two indices ## First row antibiotics[1,] ## Second column antibiotics[,2] ## Some rows and columns antibiotics[3:7, 2:4] ## Columns by name antibiotics[, c("id","temp","wbc")] ## People who received antibiotics antibiotics[antibiotics$antib==1, ] ## Put this subset into a new data frame yes <- antibiotics[antibiotics$antib==1,]
  • 23. Factors Factors represent categorical variables. You can’t do mathemat- ical operations on them (except for ==) > table(salary$rank,salary$field) Arts Other Prof Assist 668 2626 754 Assoc 1229 4229 1071 Full 942 6285 1984 > antibiotics$antib<-factor(antibiotics$antib, labels=c("Yes","No")) > antibiotics$agegp<-cut(antibiotics$antib, c(0,18,65,100)) > table(antibiotics$agegp) (0,18] (18,65] (65,100] 2 19 4
  • 24. Strings Functions for searching and modifying strings are based on reg- ular expressions, which are like simple programs for representing strings "a" matches the letter a "TATAA" matches the string TATAA "ACGT.C" matches ACGT followed by any single character, followed by C "a*b*" matches zero or more as followed by zero or more bs "[A-Za-z]+" matches one or more characters between A and Z or between a and z (in English, any letter). "[[:alpha:]]+" matches one or more letters, defined according to the current locale ".csv$" matches the string .csv at the end of a string "([[:alpha:]]+)[[:space:][:punct:]]+1[[:space:][:punct:]]+" matches any repeated word.
  • 25. Functions for regular expressions • grep(regexp, vector) finds all the strings in the vector that contain a substring matching the regular expression • sub(regexp, replacement, vector) replaces the first substring matching the regular expression with the replacement (for each element of the vector). gsub does the same thing but can make more than one replacement per string • regexpr(regexp, vector) returns the position of the first match within each string, gregexpr is the same except that it returns all matches. • strsplit() splits a string at each match to a regular expression • glob2rx() converts filename wildcard specifications to regular expressions There is also support for Perl-style regular expressions with similar functionality but different syntax
  • 26. Help • help(fn) for help on fn • help.search("topic") for help pages related to ”topic • apropos("tab") for functions whose names contain ”tab” • Search function on the http://www.r-project.org web site.
  • 27. Graphics R (and S-PLUS) can produce graphics in many formats, includ- ing: • on screen • PDF files for L A T EX or emailing to people • PNG or JPEG bitmap formats for web pages (or on non- Windows platforms to produce graphics for MS Office). PNG is also useful for graphs of large data sets. • On Windows, metafiles for Word, Powerpoint, and similar programs
  • 28. Setup Graphs should usually be designed on the screen and then may be replotted on eg a PDF file (for Word/Powerpoint you can just copy and paste) For printed graphs, you will get better results if you design the graph at the size it will end up, eg: ## on Windows windows(height=4,width=6) ## on Unix x11(height=4,width=6) Word or L A T EX can rescale the graph, but when the graph gets smaller, so do the axis labels...
  • 29. Finishing After you have the right commands to draw the graph you can produce it in another format: eg ## start a PDF file pdf("picture.pdf",height=4,width=6) ## your drawing commands here ... ### close the PDF file dev.off()
  • 30. Drawing Usually use plot() to create a graph and then lines(), points(), legend(), text(), and other commands to annotate it. plot() is a generic function: it does appropriate things for different types of input ## scatterplot plot(salary$year, salary$salary) ## boxplot plot(salary$rank, salary$salary) ## stacked barplot plot(salary$field, salary$rank) and others for other types of input. This is done by magic (actually, by advanced technology).
  • 31. Formula interface The plot() command can be written plot(salary~rank, data=salary) introducing the formula system that is also used for regression models. The variables in the formula are automatically looked up in the data= argument.
  • 32. Designing graphs Two important aspects of designing a graph • It should have something to say • It should be legible Having something to say is your problem; software can help with legibility.
  • 33. Designing graphs Important points • Axes need labels (with units, large enough to read) • Color can be very helpful (but not if the graph is going to be printed in black and white). • Different line or point styles usually should be labelled. • Points plotted on top of each other won’t be seen After these are satisfied, it can’t hurt to have the graph look nice.
  • 34. Options Set up a data set: daily ozone concentrations in New York, summer 1973 data(airquality) names(airquality) airquality$date<-with(airquality, ISOdate(1973,Month,Day)) All these graphs were designed at 4in×6in and stored as PDF files
  • 41. Notes • type= controls how data are plotted. type="n" is not as useless as it looks: it can set up a plot for latter additions. • Colors can be specified by name (the colors() function gives all the names), by red/green/blue values (#rrggbb with six base-sixteen digits) or by position in the standard palette of 8 colors. For pdf() and quartz(), partially transparent colors can be specified by #rrggbbaa. • abline draws a single straight line on a plot • ifelse() selects between two vectors based on a logical variable. • lty specifies the line type: 1 is solid, 2 is dashed, 3 is dotted, then it gets more complicated.
  • 42. Adding to a plot data(cars) plot(speed~dist,data=cars) with(cars, lines(lowess(dist,speed), col="tomato", lwd=2)) plot(speed~dist,data=cars, log="xy") with(cars, lines(lowess(dist,speed), col="tomato", lwd=2)) with(cars, lines(supsmu(dist,speed), col="purple", lwd=2)) legend(2,25, legend=c("lowess","supersmoother"),bty="n", lwd=2, col=c("tomato","purple"))
  • 43. Adding to a plot ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● 0 20 40 60 80 100 120 5 10 15 20 25 dist speed
  • 44. Adding to a plot ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●●● ● ● ● ● ● ● ● ● 2 5 10 20 50 100 5 10 15 25 dist speed
  • 45. Adding to a plot ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●●● ● ● ● ● ● ● ● ● 2 5 10 20 50 100 5 10 15 25 dist speed lowess supersmoother
  • 46. Notes • lines adds lines to an existing plot (points() adds points). • lowess() and supsmu() are scatterplot smoothers. They draw smooth curves that fit the relationship between y and x locally. • log="xy" asks for both axes to be logarithm (log="x" would just be the x-axis) • legend() adds a legend
  • 48. Boxplots ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ●● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ●● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● E H M 0 20 40 60 80 100 % new to school Level
  • 49. Notes • boxplot computes and draws boxplots. • horizontal=TRUE turns a boxplot sideways • xlab and ylab are general options for x and y axis labels.
  • 50. Barplots Use barplot to draw barplots and hist to draw histograms: barplot(VADeaths,beside=TRUE,legend=TRUE) hist(apipop$api99,col="peachpuff",xlab="1999 API", main="",prob=TRUE) • main= specifies a title for the top of the plot • prob=TRUE asks for a real histogram with probability density rather than counts.
  • 51. Rural Male Rural Female Urban Male Urban Female 50−54 55−59 60−64 65−69 70−74 0 10 20 30 40 50 60 70
  • 52. 1999 API Density 300 400 500 600 700 800 900 1000 0.0000 0.0010 0.0020
  • 53. Scatterplot matrix and color-blindness Shinobu Ishihara was a Japanese opthalmologist. While working in the Military Medical School he was asked to devise a testing system for color vision abnormalities. The original plates were hand-painted and had hiragana symbols as the patterns, a later ‘international’ edition used arabic numerals. We will examine the colors on one of these plates.
  • 54. Getting the data The first step is to get colors into R. I converted the JPEG file to a PNG file, which can then be converted to a plain text format. ## read file in SNG format, converted via PNG from JPEG disappearing<-readLines("ishihara-disappearing.sng") start<-grep("IMAGE",disappearing)+2 end<-length(disappearing)+1 disappearing<-unlist(strsplit(disappearing[start:end], "[[:space:]]")) ## remove very rare colors, which are just edge effects disappearing<-names(table(disappearing))[table(disappearing)>6] ## change rrggbb to #RRGGBB disappearing<-paste("#",toupper(disappearing),sep="")
  • 55. Color spaces The convertColor function converts between coordinate systems for color (R 2.1.0-forthcoming). Here we Lab.dis<-convertColor(matrix(disappearing), from=hexcolor, to="Lab",scale.in=NULL) The CIE Lab coordinate system is approximately perceptually uniform, with orthogonal light:dark, red:green, and blue:yellow axes.
  • 57. Blue-green points are separated from the dark red points on the b axis but not on a or L. Since the b axis is supposed to be aligned with exactly the color spectrum that is indistinguishable in red-green colorblindnesss, this explains why the tests work.
  • 58. Remapping The dichromat package in R implements a mapping that shows how colours appear to color-blind viewers. We can look at the Lab space after the transformation for protanopia
  • 60. Image plots image() plots colors to indicate values on a two-dimensional grid. A red-green spectrum is often used to code the values (especially in genomics) but this is a really bad idea. Use the dichromat package to compare red:green and blue:yellow spectra. par(mfrow=c(2,3)) x<-matrix(rnorm(10*10),10) redgreen<-colorRampPalette(c("red","green3")) image(1:10,1:10,x, col=bluescale(10), main="blue-yellow scale") image(1:10,1:10,x, col=dichromat(bluescale(10)), main="deutan") image(1:10,1:10,x,col=dichromat(bluescale(10),"protan"), main="protan") image(1:10,1:10,x, col=redgreen(10), main="red-green scale") image(1:10,1:10,x, col=dichromat(redgreen(10)), main="deutan") image(1:10,1:10,x, col=dichromat(redgreen(10),"protan"), main="protan")
  • 61. Image plots 2 4 6 8 10 2 4 6 8 10 blue−yellow scale 1:10 2 4 6 8 10 2 4 6 8 10 deutan 1:10 1:10 2 4 6 8 10 2 4 6 8 10 protan 1:10 1:10 2 4 6 8 10 2 4 6 8 10 red−green scale 2 4 6 8 10 2 4 6 8 10 deutan 1:10 2 4 6 8 10 2 4 6 8 10 protan 1:10
  • 62. Large data sets Scatterplots quickly get crowded. For example, the California Academic Performance Index is reported on 6194 schools > plot(api00~api99,data=apipop) > colors<-c("tomato","forestgreen","purple")[apipop$stype] > plot(api00~api99,data=apipop,col=colors)
  • 63. Large data sets ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● 300 400 500 600 700 800 900 400 500 600 700 800 900 api99 api00
  • 64. Large data sets ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● 300 400 500 600 700 800 900 400 500 600 700 800 900 api99 api00
  • 65. Density plots For a single large scatterplot some form of density estimation is useful library(MASS) with(apipop, image(kde2d(api99,api00), col=grey(seq(1,0.2,length=20)))) library(hexbin) with(apipop, plot(hexbin(api99,api00), style="centroids")) • kde2d in the MASS package is a 2-dimensional kernel density estimate. It returns the density of points everywhere on a rectangular grid. Variants are contour, which draws contours and filled.contour, which does coloring and contours. • image draws images from a rectangular grid of data
  • 66. Density plots • hexbin is in the hexbin package from the Bioconductor project. It computes the number of points in each hexagonal bin. • The style=centroids plot puts a filled hexagon with size depending on the number of points at the centroid of the points in the bin.
  • 67. Density plots 300 400 500 600 700 800 900 400 500 600 700 800 900
  • 69. Smoothers For showing multiple groups a scatterplot smoother or perhaps boxplots would be better. > boxplot(api00~cut(api99,(3:10)*100), data=apipop) > par(las=1) > par(mar=c(5.1,10.1,2.1,2.1)) > boxplot(api00~interaction(stype, cut(api99,(3:10)*100)), data=apipop, horizontal=TRUE,col=1:3) plot(api00~api99,data=apipop,type="n") with(subset(apipop, stype=="E"), lines(lowess(api99, api00), col="tomato")) with(subset(apipop, stype=="H"), lines(lowess(api99, api00), col="forestgreen")) with(subset(apipop, stype=="M"), lines(lowess(api99, api00), col="purple"))
  • 71. Smoothers ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● E.(300,400] H.(300,400] M.(300,400] E.(400,500] H.(400,500] M.(400,500] E.(500,600] H.(500,600] M.(500,600] E.(600,700] H.(600,700] M.(600,700] E.(700,800] H.(700,800] M.(700,800] E.(800,900] H.(800,900] M.(800,900] E.(900,1e+03] H.(900,1e+03] M.(900,1e+03] 400 500 600 700 800 900
  • 72. Smoothers 300 400 500 600 700 800 900 400 500 600 700 800 900 api99 api00
  • 73. Notes • cut turns a variable into a factor by cutting it at the specified points. • Note the use of type="n" • par(mar=) sets the margins around the plot. We need a large left margin for the labels. • subset takes a subset of a data frame.
  • 74. Example: Confidence intervals A popular plot in the lab sciences looks like: 70−74 65−69 60−64 55−59 50−54 Rural Male Rural Female Urban Male Urban Female Death Rates in Virginia 0 20 40 60 80 100 and can be created with gplots::barplot2
  • 75. Example: Confidence intervals Line plots are ordinarily preferable to bar plots, 55 60 65 70 0 20 40 60 80 100 Age Mortality rate (/1000py) Rural Male Rural Female Urban Male Urban Female
  • 76. Example: Confidence intervals but the confidence intervals get in the way 55 60 65 70 0 20 40 60 80 100 Age Mortality rate (/1000py) Rural Male Rural Female Urban Male Urban Female
  • 77. Example: Confidence intervals Offsetting the intervals slightly and coloring them helps a bit 55 60 65 70 0 20 40 60 80 100 Age Mortality rate (/1000py) Rural Male Rural Female Urban Male Urban Female
  • 78. Example: Confidence intervals We draw the confidence intervals with the segments() function. A common strategy is to plot the error bars leading up from upper curves and down from lower curves, but this is where they are least useful. Transparency is useful to allow overlap, but requires bands rather than intervals Only a few formats support transparent colors (eg PNG and PDF) and software may not support it (R does only for PDF). Colors are specified as RGBA, where the A or α channel is 1 for completely opaque and 0 for completely transparent.
  • 79. Example: Confidence intervals 55 60 65 70 0 20 40 60 80 Age Mortality rate (/1000py) Rural Male Rural Female Urban Male Urban Female
  • 80. Confidence intervals and even simultaneous confidence bands do not necessarily reflect uncertainty in the shape of a curve correctly. For example, in a plot of heart disease risk vs blood pressure we might see an increased risk for the lowest blood pressures and want to know if this increase is real. This requires simulating or bootstrapping realisations of the curve to compare to the actual curve. Simulation is most useful in a testing context, where we can generate curves under the null hypothesis.
  • 87. Conditioning plots Ozone is a secondary pollutant, it is produced from organic compounds and atmostpheric oxygen in reactions catalyzed by nitrogen oxides and powered by su nlight. However, looking at ozone concentrations in NY in summer we see a non-monotone relationship with sunlight
  • 88. Conditioning plots ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● 0 50 100 150 200 250 300 0 50 100 150 Solar.R Ozone
  • 89. Conditioning plots Here we draw a scatterplot of Ozone vs Solar.R for various subranges of Temp and Wind. A simple version of what is possible with the Trellis system. data(airquality) coplot(Ozone ~ Solar.R | Temp * Wind, number = c(4, 4), data = airquality, pch = 21, col = "goldenrod", bg = "goldenrod")
  • 90. Conditioning plots ● ● ● ● ● ● ● ● 0 50 150 ● ● ● ● ● ● ● ● ● ● ● ● ● 0 100 250 ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● 0 100 250 ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● 0 50 150 ● ● ● ● ● ● ● ● ● ● ●● ● ●● ●● ● ● ● ● ● ● ● ● ● ● 0 50 150 ● ● ●● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● 0 100 250 ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● 0 100 250 ● ● ● ● ● ● ● ● ● ● ● ● 0 50 150 Solar.R Ozone 60 70 80 90 Given : Temp 5 10 15 20 Given : Wind
  • 91. Trellis The best-known system for producing conditioning plots is Cleveland’s Trellis, in S-PLUS. There is a similar system based on Cleveland’s research in R, called lattice. Trellis is not restricted to conditioning scatterplots: it allows histograms, bo xplots, barcharts, and even 3-d plots. One dramatic example of the usefulness of these plots is the following graph of some repeatedly analyzed data on field trials of barley varieties. library(lattice) data(barley) dotplot(variety ~ yield | site, data = barley, groups = year, key = simpleKey(levels(barley$year), space = "right"))
  • 92. Dotplots: barley varieties Barley Yield (bushels/acre) 20 30 40 50 60 Svansota No. 462 Manchuria No. 475 Velvet Peatland Glabron No. 457 Wisconsin No. 38 Trebi ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● Grand Rapids ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● Duluth Svansota No. 462 Manchuria No. 475 Velvet Peatland Glabron No. 457 Wisconsin No. 38 Trebi ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● University Farm ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● Morris Svansota No. 462 Manchuria No. 475 Velvet Peatland Glabron No. 457 Wisconsin No. 38 Trebi ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● Crookston 20 30 40 50 60 ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● Waseca 1932 1931 ● ●
  • 93. Syntax notes Trellis graphics are specified by a formula: response~predictor|conditioning*variables The conditioning variables must be discrete or be shingles produced with a function such as equal.count. Some Trellis functions (eg histogram) do not have a response variable, and some (eg cloud, levelplot) have more than one predictor variable. The panel function that draws each subplot can be customised either by specifying options or by writing a new panel function. Read Cleveland’s Visualizing Data for examples (and because everyone producing statistical graphics should read it).
  • 94. R FAQ 7.22 Why do lattice/trellis graphics not work? The most likely reason is that you forgot to tell R to display the graph. Lattice functions such as xyplot() create a graph object, but do not display it (the same is true of Trellis graphics in S-Plus). The print() method for the graph object produces the actual display. When you use these functions interactively at the command line, the result is automatically printed, but in source() or inside your own functions you will need an explicit print() statement.
  • 95. Coplot: NY ozone We can produce a conditioning plot of NY summer ozone with the lattice package xyplot(Ozone~Solar.R|equal.count(Temp,4)*equal.count(Wind,4), data=airquality, strip=strip.custom(var.name=c("Temperature","Wind speed"))) The labelling is slightly different from the coplot version
  • 96. Coplot: NY ozone Solar.R Ozone 0 50 100 150 0 100 200 300 ● ● ● ● ● ● ● ● Temperature Wind Speed ● ● ● ● ● ● ● ● ● ● ● ● ● Temperature Wind Speed 0 100 200 300 ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● Temperature Wind Speed ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● Temperature Wind Speed ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● Temperature Wind Speed ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● Temperature Wind Speed ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● Temperature Wind Speed 0 50 100 150 ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● Temperature Wind Speed 0 50 100 150 ● ● ● ● ● ● ● ●● ● ●● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● Temperature Wind Speed ● ● ●● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● Temperature Wind Speed ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● Temperature Wind Speed ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● Temperature Wind Speed ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● Temperature Wind Speed 0 100 200 300 ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● Temperature Wind Speed ● ● ● ● ● ● ● ● ● ● ●● ● ● ● Temperature Wind Speed 0 100 200 300 0 50 100 150 ● ● ● ● ● ● ● ● ● ● ● ● Temperature Wind Speed
  • 97. Stereo pairs As an example of more advanced things that can be done, here is a pointless example of three-d graphics par.set <-list(axis.line = list(col = "transparent"), clip = list(panel = FALSE)) print(cloud(Sepal.Length ~ Petal.Length * Petal.Width, data = iris, cex = .8, groups = Species, main = "Stereo", screen = list(z = 20, x = -70, y = 3), par.settings = par.set), split = c(1,1,2,1), more = TRUE) print(cloud(Sepal.Length ~ Petal.Length * Petal.Width, data = iris, cex = .8, groups = Species, main = "Stereo", screen = list(z = 20, x = -70, y = 0), par.settings = par.set), split = c(2,1,2,1))
  • 98. Stereo pairs Stereo ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● Petal.Length Petal.Width Sepal.Length Stereo ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● Petal.Length Petal.Width Sepal.Length
  • 99. Mathematical annotation An expression can be specified in R for any text in a graph (help(plotmath) for details). Here we annotate a graph drawn with polygon. x<-seq(-10,10,length=400) y1<-dnorm(x) y2<-dnorm(x,m=3) par(mar=c(5,4,2,1)) plot(x,y2,xlim=c(-3,8),type="n", xlab=quote(Z==frac(mu[1]-mu[2],sigma/sqrt(n))), ylab="Density") polygon(c(1.96,1.96,x[240:400],10), c(0,dnorm(1.96,m=3),y2[240:400],0), col="grey80",lty=0) lines(x,y2) lines(x,y1) polygon(c(-1.96,-1.96,x[161:1],-10), c(0,dnorm(-1.96,m=0),y1[161:1],0), col="grey30",lty=0) polygon(c(1.96,1.96,x[240:400],10), c(0,dnorm(1.96,m=0),y1[240:400],0), col="grey30")
  • 101. Mathematical annotation −2 0 2 4 6 8 0.0 0.1 0.2 0.3 0.4 Z = µ1 − µ2 σ n Density P(Z > 1.96, H1) = 0.85 P(Z > 1.96, H0) = 0.05 H0 : µ1 = µ2 H1 : µ1 = µ2 + δ
  • 102. Managing code and data Options for storage • Workspace. When R starts it will read in the file .RData, and when it exits you are given the chance to save the workspace to that file (you can save it at any time with save.image()). This saves everything except loaded packages and is the equivalent of the .Data directory in S-PLUS. • Binary files. The save() command puts specified functions and data in a binary file. This file can be attach()ed (like a directory in S-PLUS) or load()ed. • Source code. Instead of saving results and data they can be recreated as needed from source code.
  • 103. Multiple projects There are two extreme ways to handle multiple projects in R • Store each project in a separate directory and use the .RData file to hold everything. If you want to share functions or objects with another project then explicitly export and import them. The .RData file is primary; any transcripts or source files are documentation. • Store everything as source code. For every piece of analysis have a file that reads in data, processes it, and possibly saves a modified version to a new file. The source is primary, any saved files are just a labour-saving device. The same choices apply to programming as well as data analysis, and to other dialects of S.
  • 104. Workspace is primary The first method is common among new users of S-PLUS, partly because S-PLUS automatically saves your workspace. Many of us subsequently find that we aren’t sufficiently organised to be sure that we keep records of how every analysis was done. This approach is (even) riskier in R than in S-PLUS. • In R the workspace is only saved when you explicitly ask for it; in S-PLUS it is saved frequently • In R a corrupted .RData is likely to be completely unreadable, in S-PLUS many objects will still be recoverable. It makes sense for short-term projects, especially if data loss is not critical, or for very careful people.
  • 105. Source is primary Managing projects is easy when everything can be reconstructed from source files. These files and intermediate data files can be stored in a project directory where they are easy to find and are automatically time-stamped by the operating system. Emacs Speaks Statistics (ESS) is particularly useful for this style of R use. With R running in an Emacs window you can run sections of code with a few keystrokes. The S-PLUS script window also offers many of the features of ESS.
  • 106. Logging One problem with interactive data analysis is keeping a good log of your analysis. This problem can be avoided by using interactive analysis only to construct a script that is then run to provide the final results. Other options: • ESS will capture a complete transcript, as will the Windows or Mac GUIs and the JGR GUI • in R, sink(filename, split=TRUE) will send all output to both filename and the screen. Use sink() before quitting to close the file. Note that none of these will log graphics output.
  • 107. Merging and matching The data for an analysis often do not come in a single file. Combining multiple files is necessary. If two data sets have the same individuals in the same order, they can simply be pasted together side by side. ## CHS baseline data baseline <- read.spss("I:/DISTRIB/BASEBOTH.SAV", to.data.frame=TRUE) ## Events data (eg death, heart attack, ...) events <- read.spss("I:/SAVEFILES/EVSUM04.SAV", to.data.frame=TRUE) if (!all(baseline$IDNO==events$IDNO)) { stop("PANIC: They don’t match!") } else { alldata <- cbind(baseline, events[,c("TTODTH","DEATH", "TTOMI","INCMI")]) }
  • 108. Merging: order The data might need to be sorted first index1 <- order(baseline$IDNO) baseline <- baseline[index1,] index2 <- order(events$IDNO) events <- events[index2,] if (!all(baseline$IDNO==events$IDNO)) { stop("PANIC: They still don’t match!") } else { alldata <- cbind(baseline, events[,c("TTODTH","DEATH", "TTOMI","INCMI")]) } Note that order(baseline$IDNO) gives a subset of row numbers containing all the rows but in a different (increasing) order.
  • 109. Merging: merge Or there might be different rows in the two data sets • Some people are missing from one or other data set (eg baseline and year 5 visits) • Some people have multiple records in one data set (eg baseline data and all hospitalisations The merge function can do an database outer join, giving a data set that has all the possible matches between a row in one and a row in the other
  • 110. Merging: merge combined <- merge(baseline, hospvisits, by="IDNO", all=TRUE) • by=IDNO says that the IDNO variable indicates individuals who should be matched. • all=TRUE says that even people with no records in the hospvisits data set should be kept in the merged version.
  • 111. How does it work: match You could imagine a dumb algorithm for merging for(row in firstdataset){ for(otherrow in seconddataset){ if (row$IDNO==otherrow$IDNO) ##add the row to the result } } More efficiently, the match function gives indices to match one variable to another > match(c("B","I","O","S","T","A","T"),LETTERS) [1] 2 9 15 19 20 1 20 > letters[match(c("B","I","O","S","T","A","T"),LETTERS)] [1] "b" "i" "o" "s" "t" "a" "t"
  • 112. Reshaping Sometimes data sets are the wrong shape. Data with multiple observations of similar quantities can be in long form (multiple records per person) or wide form (multiple variables per person). Example: The SeattleSNPs genetic variation discovery resource supplies data in a format SNP sample al1 al2 000095 D001 C T 000095 D002 T T 000095 D003 T T so that data for a single person is broken across many lines. To convert this to one line per person
  • 113. > data<-read.table("http://pga.gs.washington.edu/data/il6 /ilkn6.prettybase.txt", col.names=c("SNP","sample","allele1","allele2")) > dim(data) [1] 2303 4 > wideData<-reshape(data, direction="wide", idvar="sample", timevar="SNP") > dim(wideData) [1] 47 99 > names(wideData) [1] "sample" "allele1.95" "allele2.95" "allele1.205" [5] "allele2.205" "allele1.276" "allele2.276" "allele1.321" [9] "allele2.321" "allele1.657" "allele2.657" "allele1.1086" ...
  • 114. • direction="wide" says we are going from long to wide format • idvar="sample" says that sample identifies the rows in wide format • timevar="SNP" says that SNP identifies which rows go into the same column in wide form (for repeated measurements over time it would be the time variable)
  • 115. Broken down by age and sex A common request for Table 1 or Table 2 in a medical paper is to compute means and standard deviations, percentages, or frequency tables of many variables broken down by groups (eg case/control status, age and sex, exposure,...). That is, we need to apply a simple computation to subsets of the data, and apply it to many variables. One useful function is by(), another is tapply(), which is very similar (but harder to remember).
  • 116. > by(airquality$Ozone, list(month=airquality$Month), mean, na.rm=TRUE) month: 5 [1] 23.61538 ------------------------------------------------------ month: 6 [1] 29.44444 ------------------------------------------------------ month: 7 [1] 59.11538 ------------------------------------------------------ month: 8 [1] 59.96154 ------------------------------------------------------ month: 9 [1] 31.44828
  • 117. Notes • The first argument is the variable to be analyzed. • The second argument is a list of variable defining sub- sets. In this case, a single variable, but we could do list(month=airquality$Month, toohot=airquality$Temp>85) to get a breakdown by month and temperature • The third argument is the analysis function to use on each subset • Any other arguments (na.rm=TRUE) are also given to the analysis function • The result is really a vector (with a single grouping variable) or array (with multiple grouping variables). It prints differ- ently.
  • 118. Confusing digression: str() How do I know it is an array? Because str() summarises the internal structure of a variable. > a<- by(airquality$Ozone, list(month=airquality$Month, toohot=airquality$Temp>85), mean, na.rm=TRUE) > str(a) by [1:5, 1:2] 23.6 22.1 49.3 40.9 22.0 ... - attr(*, "dimnames")=List of 2 ..$ month : chr [1:5] "5" "6" "7" "8" ... ..$ toohot: chr [1:2] "FALSE" "TRUE" - attr(*, "call")= language by.data.frame(data = as.data.frame(data), INDICES = INDICES, FUN = FUN, na.rm = TRUE) - attr(*, "class")= chr "by"
  • 119. One function, many variables There is a general function, apply() for doing something to rows or columns of a matrix (or slices of a higher-dimensional array). > apply(psa[,1:8],2,mean,na.rm=TRUE) id nadir pretx ps bss grade 25.500000 16.360000 670.751163 80.833333 2.520833 2.146341 grade age obstime 2.146341 67.440000 28.460000 In this case there is a special, faster, function colMeans, but the apply can be used with other functions such as sd, IQR, min,...