# Loading relevant packages
library(tidyverse) # iris data set is found here
library (ggplot2)
#Load dataset
{data(iris)}
#Summarise dataset
head (iris) # view first 6 rows to get a brief understanding of the data set
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa
str (iris) # shows the internal strcture of the different objects
## 'data.frame': 150 obs. of 5 variables:
## $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
## $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
## $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
## $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
## $ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
From the basic summary table, we can see that the iris dataset consists of four physical characteristics of flowers, namely the sepal length, sepal width, petal length and petal width. They should all be measured and recorded in centimeters and are thus saved as numerical data types. In addition, this dataset has a species coloumn which is stored as a factor with 3 levels, where the flowers belong to 3 different species: setosa, versicolor and virginica. It is stored this way as species is a type of categorical variable. There are 50 flowers from each species, amounting to 150 records.
# Summary statistics table of all 4 variables by Species
iris_summary <- iris %>%
#Convert the dataset from wide format to long format
pivot_longer(
cols = c(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width),
names_to = "Variable", #name of measurement
values_to = "Measurement" #actual measurement value
) %>%
#Group observations by Iris species and measurement
group_by(Species, Variable) %>%
#Calculate the mean and SD for each measurement within each species
summarise(
Mean = mean(Measurement, na.rm = TRUE),
SD = sd(Measurement, na.rm = TRUE)
)
# Display the summary stats in a neat table
knitr::kable(iris_summary,
digits = 3, #round to 3dp
caption = "Summary Statistics of Petal and Sepal Dimensions by Iris Species")
| Species | Variable | Mean | SD |
|---|---|---|---|
| setosa | Petal.Length | 1.462 | 0.174 |
| setosa | Petal.Width | 0.246 | 0.105 |
| setosa | Sepal.Length | 5.006 | 0.352 |
| setosa | Sepal.Width | 3.428 | 0.379 |
| versicolor | Petal.Length | 4.260 | 0.470 |
| versicolor | Petal.Width | 1.326 | 0.198 |
| versicolor | Sepal.Length | 5.936 | 0.516 |
| versicolor | Sepal.Width | 2.770 | 0.314 |
| virginica | Petal.Length | 5.552 | 0.552 |
| virginica | Petal.Width | 2.026 | 0.275 |
| virginica | Sepal.Length | 6.588 | 0.636 |
| virginica | Sepal.Width | 2.974 | 0.322 |
From the summary statistics, we can see that for each species the values for the four physical characteristics varies. The species, virginica, has the longest mean petal length, 5.55 cm (2 d.p.), largest mean petal width, 2.03 cm (2 d.p.), as well as the longest mean sepal length, 6.59 cm (2 d.p.). However, setosa, has the largest mean sepal width, 3.43 cm (2 d.p.).
# Histogram of the 4 variables
library(patchwork) #used to combine multiple plots in one figure
#Plot 1: Sepal Length
p1 <- iris %>%
ggplot() +
#Create histogram of sepal length and colour by species
geom_histogram(
aes(x = Sepal.Length, fill = Species)
) +
#Separate the histogram into one row for each species
facet_grid(rows = vars(Species)) +
#Add axis labels and title
labs(
x = "Sepal Length (cm)",
y = "Count",
title = "Sepal Length"
) +
#Assign colours for the 3 species
scale_fill_manual(
values = c("darkorange", "purple", "cyan4")
) +
#Set graph theme and remove legend
theme_minimal() +
theme(legend.position = "none")
#Plot 2: Sepal Width
p2 <- iris %>%
ggplot() +
#Create histogram for sepal width and colour by species
geom_histogram(
aes(x = Sepal.Width, fill = Species)
) +
#Separate the histogram into one row for each species
facet_grid(rows = vars(Species)) +
#Add axis labels and title
labs(
x = "Sepal Width (cm)",
y = "Count",
title = "Sepal Width"
) +
#Assign colours for the 3 species
scale_fill_manual(
values = c("darkorange", "purple", "cyan4")
) +
#Set graph theme and remove legend
theme_minimal() +
theme(legend.position = "none")
#Plot 3: Petal Length
p3 <- iris %>%
ggplot() +
#Create histogram of petal length and colour by species
geom_histogram(
aes(x = Petal.Length, fill = Species)
) +
#Separate the histogram into one row for each species
facet_grid(rows = vars(Species)) +
#Add axis labels and title
labs(
x = "Petal Length (cm)",
y = "Count",
title = "Petal Length"
) +
#Assign colours for the 3 species
scale_fill_manual(
values = c("darkorange", "purple", "cyan4")
) +
#Set graph theme and remove legend
theme_minimal() +
theme(legend.position = "none")
#Petal Width
p4 <- iris %>%
ggplot() +
#Create histogram for petal width and colour by species
geom_histogram(
aes(x = Petal.Width, fill = Species)
) +
#Separate the histogram into one row for each species
facet_grid(rows = vars(Species)) +
#Add axis and title
labs(
x = "Petal Width (cm)",
y = "Count",
title = "Petal Width"
) +
scale_fill_manual(
values = c("darkorange", "purple", "cyan4")
) +
#Set graph theme and remove legend
theme_minimal() +
theme(legend.position = "none")
#Combine all 4 plots
(p1 | p2) /
(p3 | p4)
The histograms show clear differences in flower dimensions among the three Iris species. Sepal measurements overlap considerably between species, while petal measurements show clearer separation. Setosa has the smallest petals, versicolor has intermediate-sized petals, and virginica has the largest petals.
#Side by side Box plot of petal length and petal width
# Convert petal measurements to long format
petal_long <- iris %>%
pivot_longer(
cols = c(Petal.Length, Petal.Width),
names_to = "Petal_dimension",
values_to = "Measurement"
)
# Boxplots
ggplot(petal_long,
aes(x = Species, y = Measurement, fill = Species)) +
geom_boxplot() +
facet_wrap(~Petal_dimension, ncol = 2) +
labs(
x = "Species",
y = "Measurement (cm)",
title = "Petal Dimensions Across Iris Species"
) +
scale_fill_manual(
values = c("darkorange", "purple", "cyan4")
) +
theme_classic() +
theme(legend.position = "none")
For petal length, the measurements increases sharply from setosa to virginica. Setosa has the lowest variation in petal length measurements, with 3 outliers, whereas versicolor shows slightly greater variability with 1 outlier. As for virginica, the petal length shows the greatest variability and no outliers. Overall, virginica has the longest petal length and setosa has the shortest.
Similarly,petal width increases from setosa to virginica. The spread in petal width for all 3 species are relatively smaller than that of petal length, and only setosa has 2 outliers. Overall, virginica has the widest petals, while setosa has the narrowest.
# Summary statistics of petal width and petal length by species
petal_summary <- iris %>%
#group data by species
group_by(Species) %>%
#calculate mean and sd
summarise(
`Mean Petal Length` = mean(Petal.Length),
`SD Petal Length` = sd(Petal.Length),
`Mean Petal Width` = mean(Petal.Width),
`SD Petal Width` = sd(Petal.Width)
)
#Table
knitr::kable(
petal_summary,
digits = 3, #round to 3dp
caption = "Summary Statistics of Petal Dimensions by Iris Species"
)
| Species | Mean Petal Length | SD Petal Length | Mean Petal Width | SD Petal Width |
|---|---|---|---|---|
| setosa | 1.462 | 0.174 | 0.246 | 0.105 |
| versicolor | 4.260 | 0.470 | 1.326 | 0.198 |
| virginica | 5.552 | 0.552 | 2.026 | 0.275 |
The mean values from the summary statistics complement our findings from the boxplot graphs.