R is a software environment for statistical computing and graphics. It is open source, free to use, and has a really large and active community. There are more than 20000 packages with additional functions, tools and data sets. It is among the most used tools in data analysis and data science.
https://www.r-project.org/about.html
https://www.rdocumentation.org/
https://stackoverflow.com/questions/tagged/r
R
R is available for multiple platforms at https://cran.r-project.org/.
RStudio
RStudio is an Integrated Development Environment (IDE) for R.
It can be downloaded and installed from https://www.rstudio.com/. RStudio Desktop (Open Source License) version is available at no cost.
Calculations can be done in the RStudio console. Enter the expression, press Intro to execute.
## [1] 5
## [1] 1073741824
## [1] 4.60517
A script is a text file that contains a set of R instructions. This allows saving and restoring workflows as well as running them in unmanned mode. In R, they are commonly saved with the .R extension.
RStudio is a highly recommended editor for R. It allows creating, executing and debugging these scripts. Scripts are edited on the top-left pane.
Current selection (or instruction if nothing is selected) is executed by pressing Ctrl + Return or hitting the Run command button on the interface.
In RStudio, F1 can be used to search for the selected text in help. This works only in the pane for editing scripts.
Basic or atomic data types are
numeric: 15-digit decimal numberinteger: 32-bit integer (to ~2·109)character: character string of undefined lengthlogical: TRUE or FALSEAlthough less common in science, there are also complex and raw data types.
numericTo store numerical quantities which are continuous in nature.
## [1] 2
## [1] "numeric"
## [1] 13.6789
## [1] 13.67889568
numeric data| Addition | + |
| Subtraction | - |
| Product | * |
| Division | / |
| Power | ^ or ** |
| Modulus (remainder) | %% |
| Integer division | %/% |
| Comparisons | == > < >= <= != |
## [1] 15.6789
## [1] -11.6789
## [1] 27.35779
## [1] 13114.69
## [1] 0.1462106
integerTo store integer numbers, such as counts and indices.
## [1] "integer"
## [1] "integer"
characterTo store text (character strings) of any length.
Character-string literals are quoted (using double or single quotes).
## [1] "aaa, bbb, hola"
character data| Comparisons | == > < >= <= != |
logicalTo store values that are either TRUE or FALSE. This is the result of a comparison.
## [1] FALSE
## [1] TRUE
logical data| Logical intersection | & |
| Logical union | | |
| Logical negation | ! |
| Comparisons | == != |
For multiple logical values, any and all can be used for logical union and intersection respectively.
For example…
## [1] FALSE
## [1] TRUE
## [1] TRUE
## [1] TRUE
## [1] TRUE
Data can be converted to a different data type by using a type conversion function. These are named as. followed by the destination data type in R.
## [1] "2"
## [1] 1
Be aware that not all conversions are possible.
## Warning: NAs introduced by coercion
## [1] NA
## [1] NA
To check for a specific data type, functions is. followed by the data type are also available.
Some constants are readily available in R.
## [1] 3.141593
## [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R"
## [19] "S" "T" "U" "V" "W" "X" "Y" "Z"
Functions to check if a value matches one of these constants are also available.
## [1] FALSE
## [1] TRUE
## [1] TRUE
## num [1:3] 2 3 4
## [1] 3
Most operations are applied to vectors element-wise.
## [1] 2 3 4
## [1] 4 6 8
## [1] FALSE TRUE TRUE
Be cautious with data recycling…
## Warning in a * b: longer object length is not a multiple of shorter object
## length
## [1] 20 60 40
Most R functions take vectors and return vectors.
## [1] 0.9092974 0.1411200 0.7568025
## [1] 7.389056 20.085537 54.598150
Other returns aggregated values.
## [1] 3
## [1] 9
## [1] 3
Also sd, max, min…
The presence of an element in vector can be checked with %in%.
## [1] TRUE
## [1] TRUE FALSE TRUE TRUE
Sequence vectors are created with : or seq.
## [1] 1 2 3 4 5 6 7 8 9 10
## [1] 1 3 5 7 9
## [1] 1.0 1.5 2.0 2.5 3.0
Vectors are ordered with sort or order.
## [1] 2 3 5 8
## [1] 2 3 5 8
## [1] 8 5 3 2
## [1] 12
## [1] 13 14 15
## [1] 10 11 12 13 14 15 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
## [26] 36 37 38 39 40
## [1] 30
Create a numerical vector that includes all multiples of seven up to 1000.
Exclude the numbers that have a last digit equal to 3. Here is a hint (%% is the modulus/remainder operation): try 1004 %% 10
How many numbers are left in the vector?
How many of these numbers have a 5 in their representation?
A factor is an indexed character vector. It is usually created from a character vector.
a <- c("hola", "adeu","hola", "adeu", "adeu", "bye")
b <- as.factor(a)
as.character(b) # returns a character vector## [1] "hola" "adeu" "hola" "adeu" "adeu" "bye"
## [1] 3 1 3 1 1 2
## Factor w/ 3 levels "adeu","bye","hola": 3 1 3 1 1 2
The factor function allows manually coding or re-coding the factor.
## [1] hola adeu hola adeu adeu bye
## Levels: adeu bye hola
## [1] "adeu" "bye" "hola"
A data frame is a rectangular structure of data, organized such as each column is a vector. Different columns may be of different data types.
## int let ran
## 1 1 p -0.1379746
## 2 2 v -0.7829564
## 3 3 z 0.6669099
## 4 4 r 0.7852934
## 5 5 q 0.3175391
## 6 6 e 0.5800211
## 7 7 m 2.1969317
## 8 8 j -0.6161263
## 9 9 u 0.9853346
## 10 10 q -0.9921490
## [1] 10 3
## [1] 10
## [1] 3
## 'data.frame': 10 obs. of 3 variables:
## $ int: int 1 2 3 4 5 6 7 8 9 10
## $ let: chr "p" "v" "z" "r" ...
## $ ran: num -0.138 -0.783 0.667 0.785 0.318 ...
## int let ran
## 1 1 p -0.1379746
## 2 2 v -0.7829564
## 3 3 z 0.6669099
## int let ran
## 9 9 u 0.9853346
## 10 10 q -0.9921490
To access the data in a data frame, we use indices for row and column (starting at 1). Variables can also be selected by column name by using $.
## [1] -0.7829564
## [1] 1 2 3 4 5 6 7 8 9 10
## [1] "p" "v" "z" "r" "q" "e" "m" "j" "u" "q"
Additional options exist to select rows and columns. We’ll go into that later on.
Lists are one-dimensional structures that can store data of different types.
grades <- c("Pass", "Fail", "Good", "Fail",
"Good", "Excellent", "Pass")
grades <- factor(grades,
levels = c("Fail", "Pass",
"Good", "Excellent"),
ordered = TRUE)
str(grades)## Ord.factor w/ 4 levels "Fail"<"Pass"<..: 2 1 3 1 3 4 2
## [1] "Fail" "Pass" "Good" "Excellent"
A matrix is a rectangular data structure where all data share the same data type.
## [,1] [,2]
## [1,] 2 -1
## [2,] 4 5
## [1] 5
## [,1] [,2]
## [1,] 4 1
## [2,] 16 25
## [,1] [,2]
## [1,] 0 -7
## [2,] 28 21
## [,1] [,2]
## [1,] 2 4
## [2,] -1 5
## [1] 14
Â
## [,1] [,2]
## [1,] 0.3571429 0.07142857
## [2,] -0.2857143 0.14285714
## [,1] [,2]
## [1,] 1 5.551115e-17
## [2,] 0 1.000000e+00
Main uses of graphics and visualization in data analysis are
R includes many paradigms for graphics development. These include
base plots,ggplot2 package,lattice package,ggformula,ggvis, an interactive grammar of graphics framework, among many others.We will here discuss the simplest charts, those from base R.
base RGraphics in base R are usually constructed from vectors by using specific functions depending on the desired chart.
To exemplify some of these functions we will use the airquality data set, one of many data sets included in baseR.
Access help for details on the data set..
## 'data.frame': 153 obs. of 6 variables:
## $ Ozone : int 41 36 12 18 NA 28 23 19 8 NA ...
## $ Solar.R: int 190 118 149 313 NA NA 299 99 19 194 ...
## $ Wind : num 7.4 8 12.6 11.5 14.3 14.9 8.6 13.8 20.1 8.6 ...
## $ Temp : int 67 72 74 62 56 66 65 59 61 69 ...
## $ Month : int 5 5 5 5 5 5 5 5 5 5 ...
## $ Day : int 1 2 3 4 5 6 7 8 9 10 ...
## Ozone Solar.R Wind Temp Month Day
## 1 41 190 7.4 67 5 1
## 2 36 118 8.0 72 5 2
## 3 12 149 12.6 74 5 3
## 4 18 313 11.5 62 5 4
## 5 NA NA 14.3 56 5 5
## 6 28 NA 14.9 66 5 6
## 7 23 299 8.6 65 5 7
## 8 19 99 13.8 59 5 8
## 9 8 19 20.1 61 5 9
## 10 NA 194 8.6 69 5 10
We will show how to make
base R – scatterplotbase R – histogramWith a density curve…
base R – bar plotbase R – boxplotStatistics is the mathematics sub-discipline which covers the collection, analysis and interpretation of data. It has two main goals:
In this statistics review, we will again use the airquality data set. Details on the data set are avalable at…
## 'data.frame': 153 obs. of 6 variables:
## $ Ozone : int 41 36 12 18 NA 28 23 19 8 NA ...
## $ Solar.R: int 190 118 149 313 NA NA 299 99 19 194 ...
## $ Wind : num 7.4 8 12.6 11.5 14.3 14.9 8.6 13.8 20.1 8.6 ...
## $ Temp : int 67 72 74 62 56 66 65 59 61 69 ...
## $ Month : int 5 5 5 5 5 5 5 5 5 5 ...
## $ Day : int 1 2 3 4 5 6 7 8 9 10 ...
Often, we need to start by exploring and describing each variable data. Let’s start here.
Common aspects to consider when analyzing a single variable are
## Ozone Solar.R Wind Temp
## Min. : 1.00 Min. : 7.0 Min. : 1.700 Min. :56.00
## 1st Qu.: 18.00 1st Qu.:115.8 1st Qu.: 7.400 1st Qu.:72.00
## Median : 31.50 Median :205.0 Median : 9.700 Median :79.00
## Mean : 42.13 Mean :185.9 Mean : 9.958 Mean :77.88
## 3rd Qu.: 63.25 3rd Qu.:258.8 3rd Qu.:11.500 3rd Qu.:85.00
## Max. :168.00 Max. :334.0 Max. :20.700 Max. :97.00
## NA's :37 NA's :7
## Month Day
## Min. :5.000 Min. : 1.0
## 1st Qu.:6.000 1st Qu.: 8.0
## Median :7.000 Median :16.0
## Mean :6.993 Mean :15.8
## 3rd Qu.:8.000 3rd Qu.:23.0
## Max. :9.000 Max. :31.0
##
## [1] 153
## [1] 116
For a quantitative variable (numeric)…
##
## (0,50] (50,100] (100,150] (150,200] (200,250] (250,300] (300,350]
## 17 17 18 19 30 36 9
##
## (0,50] (50,100] (100,150] (150,200] (200,250] (250,300] (300,350]
## 0.11643836 0.11643836 0.12328767 0.13013699 0.20547945 0.24657534 0.06164384
For a qualitative variable (usually factor)…
##
## 5 6 7 8 9
## 31 30 31 31 30
##
## 5 6 7 8 9
## 0.2026144 0.1960784 0.2026144 0.2026144 0.1960784
## 10%
## 5.82
## 0% 20% 40% 60% 80% 100%
## 1.70 6.90 8.60 10.42 12.96 20.70
# Excel PERCENTILE and R default are type 7
c(min = min(airquality$Wind), quantile(airquality$Wind,0:5*.2),
max = max(airquality$Wind)) ## min 0% 20% 40% 60% 80% 100% max
## 1.70 1.70 6.90 8.60 10.42 12.96 20.70 20.70
# Excel PERCENTILE.EXC, SPSS and Minitab default are type 6
c(min = min(airquality$Wind), quantile(airquality$Wind,0:5*.2, type=6),
max = max(airquality$Wind))## min 0% 20% 40% 60% 80% 100% max
## 1.70 1.70 6.90 8.60 10.54 13.20 20.70 20.70
## [1] NA
## [1] 42.12931
## [1] 31.5
## [1] 1088.201
## [1] 32.98788
## [1] 1 168
## [1] 167
## [1] 45.25
## [1] 25.9455
There are different methods to analyze outliers in R. A nice description can be found at https://statsandr.com/blog/outliers-detection-in-r/
# Hampel filter
lmin <- median(airquality$Wind,.25) - 3 * mad(airquality$Wind)
lmax <- median(airquality$Wind,.75) + 3 * mad(airquality$Wind)
c(as.numeric(lmin),as.numeric(lmax))## [1] -0.52994 19.92994
## [1] 20.1 20.7
# IQR method
lmin <- quantile(airquality$Wind,.25) - 1.5 * IQR(airquality$Wind)
lmax <- quantile(airquality$Wind,.75) + 1.5 * IQR(airquality$Wind)
c(as.numeric(lmin),as.numeric(lmax))## [1] 1.25 17.65
## [1] 20.1 18.4 20.7
## [1] 20.1 18.4 20.7
Plots are also useful to describe a data set.
To study and describe the relation between two variables, common techniques include
The contingency table is a two-way frequency table.
table(cut(airquality$Wind,breaks = seq(1,21,by=5)),
cut(airquality$Temp,breaks = seq(50,100,by=10)))##
## (50,60] (60,70] (70,80] (80,90] (90,100]
## (1,6] 0 0 3 8 5
## (6,11] 2 12 29 33 8
## (11,16] 4 10 18 13 1
## (16,21] 2 3 2 0 0
## [1] -0.4579879
## [1] -0.4465408
A probability distribution of a random number corresponds to the abstraction of the density distribution of a set of infinite number of data with the same origin.
A large number of experimental distributions have related theoretical models. The most common theoretical distributions are the normal distribution (for continuous variables), the uniform distribution (for continuous or discrete variables), and the binomial distribution (for the number of successes of a discrete event with a defined probability).
In R, all theoretical distributions share the same system of functions
r<dist>: to generate random numbers according to the distributiond<dist>: to calculate the density for a value of the variableq<dist>: to obtain the value of the variable (quantile) for an accumulated probabilityp<dist>: to obtain the accumulated probability for a value of the variableFor example, for the normal distribution…
## [1] -0.9522090 -1.5679102 -1.6130521 1.6609033 0.3676980 0.2388170
## [7] -0.1741726 1.1842770 -1.2577507 0.5258397
## [1] 0.3989423
## [1] 1.644854
## [1] 0.9494974
## [1] 0.9772499
## [1] 5.053749
## [1] 0.8413447 0.9772499 0.9986501 0.9999683 0.9999997
## [1] 1.644854 1.959964 2.326348 2.575829 3.090232
## [1] 0.2
## [1] 19
## [1] 0.5
## [1] 2
R includes many other distributions that can be looked up in the help files.
In statistics, inference is the determination of information about the population –the entire set of existing values– from a representative sample and some data model hypothesis.
In case the sample is not representative, any information inferred from it will be biased, potentially displaced from its actual value.
Inference results are commonly shown in either of the following two formats:
We will be reviewing here, while we show how to apply them in R, the most common procedures
To test the fit to a theoretical distribution, the most common test are the chi-squared goodness-of-fit test (chisq.test) and the test of Kolmogorov-Smirnov (ks.test). In both cases, the arguments are the observed absolute frequencies and the probabilities expected according to the theoretical distribution.
NOTE: The ks.test is not appropriate when the distribution to test is fitted to the sample data –i.e. for the Lilliefors test for normality.
A 10-face dice is thrown a hundred times. The table below shows the results for the experiment.
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|
| 9 | 6 | 7 | 15 | 11 | 11 | 9 | 13 | 9 | 10 |
If the dice was normal, each face should have the same probality of appearing. Is it the case?
##
## Chi-squared test for given probabilities
##
## data: obs
## X-squared = 6.4, df = 9, p-value = 0.6993
Although with less objectivity, graphical methods can also be used to compare distributions. This is usually done through a quantile-quantile plot –in R, qqplot.
If both data sets belong to the same distribution, their quantiles will appear aligned on the diagonal of the plot (especially on the central region of the chart).
To check if a data set might be a random sample of a population following a normal distribution, there are specific tests. Among the most common ones, there are the Shapiro-Wilk normality test and the Anderson-Darling normality test. Only the former is available in R base.
x1 <- rnorm(20, mean = 4, sd = 5)
x2 <- rbeta(20, shape1 = 5, shape2 = .5, ncp = 4)
shapiro.test(x1)##
## Shapiro-Wilk normality test
##
## data: x1
## W = 0.98405, p-value = 0.9752
##
## Shapiro-Wilk normality test
##
## data: x2
## W = 0.70892, p-value = 5.018e-05
Graphically, the quantile-quantile plot can also be used. In R, the qqnorm function provide a direct comparison with the normal distribution.
The most common inferences respect to the spread of a population fall in the following cases:
When sample dats come from a normal distribution, the confidence interval for the variance can be calculated from the chi-squared distribution.
x <- rnorm(50, mean = 0, sd = 2)
df <- length(x) - 1
lower <- var(x) * df / qchisq(1 - 0.05/2, df)
upper <- var(x) * df / qchisq(0.05/2, df)
c(lower = lower, var = var(x), upper = upper)## lower var upper
## 3.376276 4.838577 7.513576
To calculate the confidence interval for the standard deviation, when data come from a normal distribution, we proceed by taking the square root of the limits of the confidence interval for the variance.
## lower sd upper
## 1.837465 2.199677 2.741090
To compare the spread of two populations, when data come from normal distributions, we use an F test – var.test in R–.
##
## F test to compare two variances
##
## data: x and y
## F = 4.8734, num df = 49, denom df = 29, p-value = 2.054e-05
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
## 2.448522 9.168943
## sample estimates:
## ratio of variances
## 4.873426
If the data don’t come from a normally distributed population, spreads (scales) can be compared with the Ansari-Bradley test.
##
## Ansari-Bradley test
##
## data: x and y
## AB = 834, p-value = 0.0001463
## alternative hypothesis: true ratio of scales is not equal to 1
To compare the spread (scales) of more than two normally distributed populations, the Bartlett test –bartlett.test in R– is commonly used.
## [[1]]
## [1] -1.1 0.3 1.1 -0.2 3.9 2.3 2.3 -0.4 -1.0 -2.5 -2.5 -0.4 1.9 0.3 3.1
## [16] -0.5 -2.3 -0.5 -0.3 0.4
##
## [[2]]
## [1] 2.8 9.1 0.9 0.6 6.0 -0.8 1.1 0.7 1.5 3.6 4.4 3.6 2.4 3.3 5.3
## [16] 3.1 -1.2 4.1 1.5 1.4
##
## [[3]]
## [1] 6.0 2.8 4.3 8.0 5.3 4.6 4.2 8.0 0.7 4.1 6.0 3.2 7.9 6.1 8.5 6.1 7.1 6.6
## [19] 4.9 6.0
##
## Bartlett test of homogeneity of variances
##
## data: list(x1, x2, x3)
## Bartlett's K-squared = 1.841, df = 2, p-value = 0.3983
In case any of the populations is not normally distributed, Fligner-Killeen test –in R, fligner.test–, Levene test –leveneTest in the R car package– or Brown–Forsythe test –bf.test in the R onewaytests package– can be useful.
Graphically, although with less objectivity, either boxplots or boxplots of the centered data can be used.
x1 <- round(rnorm(20, mean = 1, sd = 2),1)
x2 <- round(rnorm(20, mean = 3, sd = 2),1)
x3 <- round(rnorm(20, mean = 5, sd = 2),1)
xs <- data.frame(
group = factor(c(rep(1, length(x1)),rep(2, length(x2)),
rep(3, length(x3)))),
y = c(x1,x2,x3),
centered = c(x1 - median(x1),x2 - median(x2),x3 - median(x3)))
boxplot(y~group,data=xs)
boxplot(centered~group,data=xs)The main inferences for location –or central tendency– of a population correspond to
To calculate a confidence interval for the mean of a normally distributed population, we use the Student (or t) distribution. In R, it can be calculates form the qt function, or also as one of the results of the t.test function.
## [1] 1.686929 1.239502 1.512727 2.213534 2.412221 1.880277 1.490086 1.638548
## [9] 1.720624 1.735600
##
## One Sample t-test
##
## data: x
## t = 16.061, df = 9, p-value = 6.224e-08
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
## 1.506093 1.999917
## sample estimates:
## mean of x
## 1.753005
If the population does not follow a normal distribution, a nonparametric confidence interval for the median can be calculated by using the wilcox.test function.
## [1] 33.965428 7.775225 35.998212 41.158842 5.936732 22.713098 13.283428
## [8] 40.740159 15.711430 23.143556
##
## Wilcoxon signed rank exact test
##
## data: x
## V = 55, p-value = 0.001953
## alternative hypothesis: true location is not equal to 0
## 95 percent confidence interval:
## 14.32492 34.98182
## sample estimates:
## (pseudo)median
## 23.62443
Both function presented to obtain the confidence intervals, can also compare the central tendency of a population to a predefined value. As already said, the t test works for a normally distributed population; the Wilcoxon test does not have this requirement.
## [1] 1.223791 3.085184 1.852469 1.693080 1.445404 2.725965 1.348104 1.618911
## [9] 1.970554 1.656257
##
## One Sample t-test
##
## data: x
## t = 1.9109, df = 9, p-value = 0.08834
## alternative hypothesis: true mean is not equal to 1.5
## 95 percent confidence interval:
## 1.433460 2.290483
## sample estimates:
## mean of x
## 1.861972
## [1] 4.698333
##
## Wilcoxon signed rank exact test
##
## data: x^3
## V = 19, p-value = 0.4316
## alternative hypothesis: true location is not equal to 8
To compare the location of two populations, three prior considerations should be made.
Data are associated or paired when there are pairs of values –one from each data set– that share some sources of variation (same person, same object, same date…). In this case
t.test with a single vector as argument, or directly use the t.test with paired = TRUE,wilcox.test on the difference o with the option paired = TRUE in R–.## $x
## [1] 1.277681 2.914682 3.925041 1.969814 2.342574 2.544146 4.189742 5.411424
## [9] 3.656713 3.905103
##
## $y
## [1] 3.452561 3.609724 2.611078 3.210655 4.854134 3.292235 3.352783 4.421090
## [9] 2.439111 4.480826
##
## One Sample t-test
##
## data: x - y
## t = -0.81223, df = 9, p-value = 0.4376
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
## -1.3578218 0.6403664
## sample estimates:
## mean of x
## -0.3587277
##
## Paired t-test
##
## data: x and y
## t = -0.81223, df = 9, p-value = 0.4376
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -1.3578218 0.6403664
## sample estimates:
## mean of the differences
## -0.3587277
## $x
## [1] 8.838918 39.863507 11.884782 104.695701 12.867779 11.064775
## [7] 15.294796 3.190878 40.972356 38.489396
##
## $y
## [1] 4.103173 37.568402 13.747714 18.069986 13.385564 16.096291 13.268866
## [8] 72.866033 13.594474 48.260085
##
## Wilcoxon signed rank exact test
##
## data: x - y
## V = 30, p-value = 0.8457
## alternative hypothesis: true location is not equal to 0
##
## Wilcoxon signed rank exact test
##
## data: x and y
## V = 30, p-value = 0.8457
## alternative hypothesis: true location shift is not equal to 0
If data samples are not associated then
t.test; the option var.equal allows switching between the test assuming equality of population variances and the Welch t-test, which is the default and does not requires this assumption;wilcox.test in R–.## $x
## [1] 0.7100998 2.8503600 1.4712753 1.6682625 4.3117188 3.8645828 0.4823599
## [8] 4.7560051 2.4609516 2.4143930
##
## $y
## [1] 3.1821818 3.6184593 -0.3071339 5.3237185 0.7557177 3.8444313
## [7] 4.2947082 4.6667955 3.9700982 5.0681868 5.3941933 3.7802958
## [13] 2.9330113 3.3024634
##
## Welch Two Sample t-test
##
## data: x and y
## t = -1.6687, df = 20.669, p-value = 0.1103
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -2.3824710 0.2623118
## sample estimates:
## mean of x mean of y
## 2.499001 3.559081
## $x
## [1] 18.802748 66.089945 32.256945 46.944341 16.552733 47.380105 22.442650
## [8] 17.104187 8.200203 12.809117
##
## $y
## [1] 7903.665068 1.196672 40.273679 6.921986 5.150989 4.786479
## [7] 216.578951 21.579357 18.274133 20.104265 194.860434 32.862766
## [13] 18.257845 7.930001
##
## Wilcoxon rank sum exact test
##
## data: x and y
## W = 78, p-value = 0.6665
## alternative hypothesis: true location shift is not equal to 0
To compare locations for three o more populations, the most used procedures are
aov in R–;oneway.test in R–;krukal.test–. More details can be found at https://rcompanion.org/handbook/F_08.html.x <- c(rnorm(10, mean = 3, sd = 1),
rnorm(8, mean = 3.2, sd = 1),
rnorm(10, mean = 4, sd = 1))
g <- factor(c(rep(1,10), rep(2,8), rep(3,10)))
test <- aov(x ~ g)
summary(test)## Df Sum Sq Mean Sq F value Pr(>F)
## g 2 14.70 7.348 13.85 8.93e-05 ***
## Residuals 25 13.26 0.530
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
x <- c(rnorm(10, mean = 3, sd = 1),
rnorm(8, mean = 3.2, sd = 4),
rnorm(10, mean = 4, sd = 2))
g <- factor(c(rep(1,10), rep(2,8), rep(3,10)))
oneway.test(x ~ g)##
## One-way analysis of means (not assuming equal variances)
##
## data: x and g
## F = 6.2297, num df = 2.000, denom df = 12.815, p-value = 0.01288
x <- c(runif(10, min = 2, max = 4),
runif(8, min = 1.5, max = 3.5),
runif(10, min = 3, max = 5))
g <- factor(c(rep(1,10), rep(2,8), rep(3,10)))
kruskal.test(x ~ g)##
## Kruskal-Wallis rank sum test
##
## data: x by g
## Kruskal-Wallis chi-squared = 16.245, df = 2, p-value = 0.0002968
Either the ANOVA or the Kruskal-Wallis test only whether there is a difference among the populations or not, but they can not identify what populations (groups) differ in location.
To test which pairs of populations have different locations, we use post-hoc tests.
TukeyHSD in R,dunn.test in the dunn.test R package–Graphically, although with less objectivity, a boxplot can be used to compare location of different data sets.
A model is commonly expressed in R with a formula object.
In this notation, relation among variables is indicated through a three-term expression, with the dependent variable on the left, a tilde operator (~) and a combination of independent variables on the right side
## [1] "formula"
Ordinary least square (OLS) fit can be produced in R, by using the lm function. They can also be used for factors; in this case, dummy variables are produced for the levels of the factors (all but the first one).
##
## Call:
## lm(formula = Ozone ~ Solar.R, data = airquality)
##
## Residuals:
## Min 1Q Median 3Q Max
## -48.292 -21.361 -8.864 16.373 119.136
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 18.59873 6.74790 2.756 0.006856 **
## Solar.R 0.12717 0.03278 3.880 0.000179 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 31.33 on 109 degrees of freedom
## (42 observations deleted due to missingness)
## Multiple R-squared: 0.1213, Adjusted R-squared: 0.1133
## F-statistic: 15.05 on 1 and 109 DF, p-value: 0.0001793
##
## Call:
## lm(formula = Ozone ~ Solar.R + Temp, data = airquality)
##
## Residuals:
## Min 1Q Median 3Q Max
## -36.610 -15.976 -2.928 12.371 115.555
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -145.70316 18.44672 -7.899 2.53e-12 ***
## Solar.R 0.05711 0.02572 2.221 0.0285 *
## Temp 2.27847 0.24600 9.262 2.22e-15 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 23.5 on 108 degrees of freedom
## (42 observations deleted due to missingness)
## Multiple R-squared: 0.5103, Adjusted R-squared: 0.5012
## F-statistic: 56.28 on 2 and 108 DF, p-value: < 2.2e-16
##
## Call:
## lm(formula = Temp ~ Month, data = df)
##
## Residuals:
## Min 1Q Median 3Q Max
## -14.100 -4.548 -0.900 3.900 16.100
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 65.548 1.195 54.831 < 2e-16 ***
## Month6 13.552 1.705 7.950 4.40e-13 ***
## Month7 18.355 1.691 10.857 < 2e-16 ***
## Month8 18.419 1.691 10.895 < 2e-16 ***
## Month9 11.352 1.705 6.659 5.05e-10 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 6.656 on 148 degrees of freedom
## Multiple R-squared: 0.5185, Adjusted R-squared: 0.5055
## F-statistic: 39.85 on 4 and 148 DF, p-value: < 2.2e-16
Once fitted, the model can be used to predict the dependent variable with the predict function. To search for help, look up predict.lm.
df <- na.omit(data.frame(x=airquality$Solar.R, y=airquality$Ozone,
predict(fit1, newdata=airquality, interval="prediction")))
head(df)## x y fit lwr upr
## 1 190 41 42.76013 -19.624006 105.14426
## 2 118 36 33.60423 -28.929745 96.13820
## 3 149 12 37.54635 -24.880207 99.97291
## 4 313 18 58.40146 -4.535186 121.33810
## 7 299 23 56.62114 -6.201625 119.44391
## 8 99 19 31.18809 -31.443642 93.81982
The model can be represented from the predictions.
df2 <- data.frame(
Solar.R = seq(min(airquality$Solar.R,na.rm=TRUE),
max(airquality$Solar.R,na.rm=TRUE), length.out = 201))
df2 <- cbind(df2, predict(fit1,
newdata = df2, interval="prediction"))
plot(range(df2$Solar.R),range(c(df2$lwr,df2$upr)),type="n")
lines(df2$Solar.R,df2$fit,type="l",lwd=2)
lines(df2$Solar.R,df2$upr,col="grey",lwd=1)
lines(df2$Solar.R,df2$lwr,col="grey",lwd=1)
points(airquality$Solar.R,airquality$Ozone,pch="+")To check the goodness and correctness of the fitted model and the fitting approach (OLS), the residuals should be analyzed. They should be random, normally distributed, homocedastic and high-leverage points should not be present.
These checks can be made from the residuals data and the required statistical tests.
## Solar.R Ozone fit res
## 1 190 41 42.76013 -1.760129
## 2 118 36 33.60423 2.395770
## 3 149 12 37.54635 -25.546353
## 4 313 18 58.40146 -40.401458
## 7 299 23 56.62114 -33.621144
## 8 99 19 31.18809 -12.188090
##
## Shapiro-Wilk normality test
##
## data: fit1$residuals
## W = 0.91418, p-value = 2.516e-06
##
## Fligner-Killeen test of homogeneity of variances
##
## data: fit1$residuals and cut(1:length(fit1$residuals), breaks = 3)
## Fligner-Killeen:med chi-squared = 4.8771, df = 2, p-value = 0.08729
##
## Fligner-Killeen test of homogeneity of variances
##
## data: fit1$residuals and cut(fit1$fitted.values - median(fit1$fitted.values), breaks = 3)
## Fligner-Killeen:med chi-squared = 15.312, df = 2, p-value = 0.0004733
Graphically, the same aspects can be informed from the plots of the model.
Parallel approaches are followed when fitting more complex multilinear models (lm), generalized linear models (glm), or non-linear models by least-squares (nls), among other options.
base functions)As introduced above, data frames are the most common data structure to store data sets.
Often preparing the data in specific formats is a requirement for producing data visualizations or running statistical procedures. We will dedicate this block to discuss some common operations in data wrangling. Additional operations will be discussed later on.
Common operations on data frame are
We will discuss the first six operations here, as these are often done with base R functions.
The last two operations will be explained when introducing the dplyr R package.
Let’s start synthetic data frame…
## number letters.1.5. c.rep..a...3...rep..b...2..
## 1 1 a a
## 2 2 b a
## 3 3 c a
## 4 4 d b
## 5 5 e b
## var1 var2 var3
## subject001 1 a a
## subject002 2 b a
## subject003 3 c a
## subject004 4 d b
## subject005 5 e b
df2 <- cbind(df, rnorm(5)) # adding a vector to the data frame
df2$var5 <- 5:1 # assigning values to a new named column
df2## var1 var2 var3 rnorm(5) var5
## subject001 1 a a -0.8559106 5
## subject002 2 b a 0.2775033 4
## subject003 3 c a 0.9535050 3
## subject004 4 d b -1.0600254 2
## subject005 5 e b -0.2480291 1
## var1 var2 var3
## subject001 1 a a
## subject002 2 b a
## subject003 3 c a
## subject004 4 d b
## subject005 5 e b
## 1 6 e b
There are three basic ways to segment a data frame by selecting rows and columns
## var1 var2 var3
## subject001 1 a a
## subject002 2 b a
## subject003 3 c a
## var1 var3
## subject001 1 a
## subject002 2 a
## subject003 3 a
## subject004 4 b
## subject005 5 b
Using negative indices removes rows or columns
## var1 var3
## subject001 1 a
## subject002 2 a
## subject005 5 b
## [1] "a" "b" "c" "d" "e"
## [1] "a" "a" "a" "b" "b"
## var2 var3
## subject001 a a
## subject002 b a
## subject003 c a
## subject004 d b
## subject005 e b
## var1 var3
## subject001 1 a
## subject002 2 a
## subject004 4 b
## var1 var2 var3
## subject003 3 c a
## subject004 4 d b
## subject005 5 e b
The most common way of removing columns or rows is segmenting the data frame. However a column can also be removed by assign it to NULL.
## var1 var3
## subject001 1 a
## subject003 3 a
## subject004 4 b
## subject005 5 b
Rows with NA values can be removed with the na.omit function.
## var1 var3
## subject001 1 a
## subject004 4 b
## subject005 5 b
In case we want to remove a variable from the environment, we use the rm function.
## A B C
## 1 -1 -1 0
## 2 1 -1 0
## 3 -1 1 0
## 4 1 1 0
## 5 -1 -1 1
## 6 1 -1 1
## 7 -1 1 1
## 8 1 1 1
## 9 -1 -1 2
## 10 1 -1 2
## 11 -1 1 2
## 12 1 1 2
Data frames can be joined on common values for the combining variables by using the merge function. By default, they are merged on the variables with same names.
dfC <- data.frame(C=c(0,1,2),
condC=c("hexane","cyclohexane","THF"))
dfExp <- merge(dfExp, dfC)
head(dfExp)## C A B condC
## 1 0 -1 -1 hexane
## 2 0 1 -1 hexane
## 3 0 -1 1 hexane
## 4 0 1 1 hexane
## 5 1 -1 -1 cyclohexane
## 6 1 1 -1 cyclohexane
OrchardSprays data set.Run help("OrchardSprays") to know more about the experiment and the data set.