Bước 1: Khám phá dữ liệu

# Xem tóm tắt dữ liệu
summary(iris)
##   Sepal.Length    Sepal.Width     Petal.Length    Petal.Width   
##  Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100  
##  1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300  
##  Median :5.800   Median :3.000   Median :4.350   Median :1.300  
##  Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199  
##  3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800  
##  Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500  
##        Species  
##  setosa    :50  
##  versicolor:50  
##  virginica :50  
##                 
##                 
## 
# Hiển thị tên cột và chuyển sang chữ thường để dễ thao tác
names(iris)
## [1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"  "Species"
names(iris) <- tolower(names(iris))
names(iris)
## [1] "sepal.length" "sepal.width"  "petal.length" "petal.width"  "species"
# Kích thước và kiểu dữ liệu
dim(iris)
## [1] 150   5
class(iris)
## [1] "data.frame"
# Kiểm tra kiểu và cấu trúc của các biến cụ thể
typeof(iris$sepal.length)
## [1] "double"
str(iris$sepal.length)
##  num [1:150] 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
typeof(iris$species)
## [1] "integer"
class(iris$species)
## [1] "factor"
str(iris$species)
##  Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...

Bước 2: Chỉnh sửa và thay đổi cấu trúc dữ liệu

# Tách subset cho loài virginica
virginica  <- iris %>% filter(species == "virginica")
virginica2 <- iris %>% filter(species == "virginica", sepal.length > 6)
head(virginica)
##   sepal.length sepal.width petal.length petal.width   species
## 1          6.3         3.3          6.0         2.5 virginica
## 2          5.8         2.7          5.1         1.9 virginica
## 3          7.1         3.0          5.9         2.1 virginica
## 4          6.3         2.9          5.6         1.8 virginica
## 5          6.5         3.0          5.8         2.2 virginica
## 6          7.6         3.0          6.6         2.1 virginica
# Chọn cột sepal.length và sepal.width
selected <- iris %>% select(sepal.length, sepal.width)
head(selected)
##   sepal.length sepal.width
## 1          5.1         3.5
## 2          4.9         3.0
## 3          4.7         3.2
## 4          4.6         3.1
## 5          5.0         3.6
## 6          5.4         3.9
# Thêm cột mới tính tỷ lệ và điều kiện
newcol <- iris %>%
  mutate(
    longer    = sepal.length / sepal.width,
    longer.2x = sepal.length > 2 * sepal.width
  )
tail(newcol)
##     sepal.length sepal.width petal.length petal.width   species   longer
## 145          6.7         3.3          5.7         2.5 virginica 2.030303
## 146          6.7         3.0          5.2         2.3 virginica 2.233333
## 147          6.3         2.5          5.0         1.9 virginica 2.520000
## 148          6.5         3.0          5.2         2.0 virginica 2.166667
## 149          6.2         3.4          5.4         2.3 virginica 1.823529
## 150          5.9         3.0          5.1         1.8 virginica 1.966667
##     longer.2x
## 145      TRUE
## 146      TRUE
## 147      TRUE
## 148      TRUE
## 149     FALSE
## 150     FALSE
# Sắp xếp dữ liệu
newcol_sorted1 <- newcol %>% arrange(sepal.width)
newcol_sorted2 <- newcol %>% arrange(desc(sepal.width))

# Unpivot (melt) dữ liệu
iris_melt <- melt(iris, id.vars = "species", variable.name = "size")
head(iris_melt)
##   species         size value
## 1  setosa sepal.length   5.1
## 2  setosa sepal.length   4.9
## 3  setosa sepal.length   4.7
## 4  setosa sepal.length   4.6
## 5  setosa sepal.length   5.0
## 6  setosa sepal.length   5.4

Bước 3: Trực quan hóa dữ liệu

## Histogram cơ bản
hist(iris$sepal.length)

## Histogram với tùy chỉnh màu và breaks
hist(
  iris$sepal.length,
  col    = "lightblue",
  main   = "Histogram of Sepal Length",
  xlab   = "Sepal Length",
  ylab   = "Frequency"
)

## So sánh Sepal và Petal Length trên cùng biểu đồ
hist(
  iris$sepal.length,
  col    = "gold",
  breaks = 20,
  main   = "Histogram: Sepal vs Petal Length",
  xlab   = "Size"
)
hist(
  iris$petal.length,
  col    = "lightgreen",
  breaks = 30,
  add    = TRUE
)
legend(
  "topright",
  legend = c("Sepal Length", "Petal Length"),
  fill   = c("gold", "lightgreen")
)

## Histogram với ggplot2
ggplot(iris_melt, aes(x = value, fill = size)) +
  geom_histogram(color    = "#e9ecef",
                 alpha    = 0.6,
                 position = "identity")

## Facet theo biến size
ggplot(iris_melt, aes(x = value, fill = size)) +
  geom_histogram(color    = "#e9ecef",
                 alpha    = 0.6,
                 position = "identity") +
  facet_wrap(~ size)

## Boxplot cơ bản
boxplot(
  sepal.length ~ species,
  data  = iris,
  main  = "Sepal Length by Species",
  xlab  = "Species",
  ylab  = "Sepal Length",
  col   = "lightblue",
  border= "black"
)

## Boxplot từ dữ liệu melt
boxplot(
  value ~ size,
  data  = iris_melt,
  main  = "Compare Different Sizes",
  xlab  = "Size",
  ylab  = "Value",
  col   = "lightblue",
  border= "black"
)

## Boxplot và jitter với ggplot2
ggplot(iris_melt, aes(x = size, y = value, fill = size)) +
  geom_boxplot() +
  geom_jitter(color = "black", size = 0.4, alpha = 0.9)

## Scatter plots cơ bản
plot(iris)

plot(iris[, 1:4])

plot(
  iris$sepal.width,
  iris$sepal.length,
  col   = "steelblue",
  main  = "Scatterplot of Sepal",
  xlab  = "Sepal Width",
  ylab  = "Sepal Length",
  pch   = 19
)

## Pair plot
pairs(
  iris[, 1:4],
  col = iris[, 5],
  oma = c(4,4,6,12),
  xpd = TRUE
)

## ggplot scatter với phân loại
ggplot(iris, aes(x = sepal.length, y = sepal.width, color = species)) +
  geom_point(size = 5)

## GGally pairs
GGally::ggpairs(
  iris,
  columns = 1:4,
  aes(color = species, alpha = 0.5)
)

Bước 4: Kiểm định giả định với T-test

setosa     <- iris %>% filter(species == "setosa")
versicolor <- iris %>% filter(species == "versicolor")

t.test(
  x = setosa$petal.length,
  y = versicolor$petal.length
)
## 
##  Welch Two Sample t-test
## 
## data:  setosa$petal.length and versicolor$petal.length
## t = -39.493, df = 62.14, p-value < 2.2e-16
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -2.939618 -2.656382
## sample estimates:
## mean of x mean of y 
##     1.462     4.260

Bước 5: Phân tích ANOVA

petal_length_aov <- aov(petal.length ~ species, data = iris)

# Kết quả ANOVA
summary(petal_length_aov)
##              Df Sum Sq Mean Sq F value Pr(>F)    
## species       2  437.1  218.55    1180 <2e-16 ***
## Residuals   147   27.2    0.19                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# Kiểm định sau ANOVA
TukeyHSD(petal_length_aov)
##   Tukey multiple comparisons of means
##     95% family-wise confidence level
## 
## Fit: aov(formula = petal.length ~ species, data = iris)
## 
## $species
##                       diff     lwr     upr p adj
## versicolor-setosa    2.798 2.59422 3.00178     0
## virginica-setosa     4.090 3.88622 4.29378     0
## virginica-versicolor 1.292 1.08822 1.49578     0

Bước 6: Phân loại với k-mean

iris.test <- iris

iris.test$species <- NULL

head(iris.test)
##   sepal.length sepal.width petal.length petal.width
## 1          5.1         3.5          1.4         0.2
## 2          4.9         3.0          1.4         0.2
## 3          4.7         3.2          1.3         0.2
## 4          4.6         3.1          1.5         0.2
## 5          5.0         3.6          1.4         0.2
## 6          5.4         3.9          1.7         0.4
kmeans.result <- kmeans(iris.test, 3)

table(iris$species, kmeans.result$cluster)
##             
##               1  2  3
##   setosa     50  0  0
##   versicolor  0 48  2
##   virginica   0 14 36
plot(iris.test[c('sepal.length', 'sepal.width')], col = kmeans.result$cluster)

plotcluster(iris.test, kmeans.result$cluster)

clusplot(iris.test, kmeans.result$cluster, color = TRUE, shade = TRUE)