Kelompok 11

- Haidar Ramdhani (G1401221005)

- Raihana Asma Amani (G1401221039)

- Sabrina Afifah Putri Utami (G1401221035)

Read Data

Data yang digunakan adalah data kesehatan tidur dan gaya sehat yang diperoleh dari kaggle.com. Terdapat 13 kolom pada data ini yang merupakan gabungan dari data kategorik dan numerik, dengan jumlah 374 baris.

Library dan Input Data

library(readxl)
## Warning: package 'readxl' was built under R version 4.3.2
library(reshape2)
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.3.2
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(plyr)
## ------------------------------------------------------------------------------
## You have loaded plyr after dplyr - this is likely to cause problems.
## If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
## library(plyr); library(dplyr)
## ------------------------------------------------------------------------------
## 
## Attaching package: 'plyr'
## The following objects are masked from 'package:dplyr':
## 
##     arrange, count, desc, failwith, id, mutate, rename, summarise,
##     summarize
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
data <- read.csv("D:\\Campss\\Season 4\\Visdat\\Project Prak\\Sleep_health_and_lifestyle_dataset.csv", sep = ",")
summary(data)
##    Person.ID         Gender               Age         Occupation       
##  Min.   :  1.00   Length:374         Min.   :27.00   Length:374        
##  1st Qu.: 94.25   Class :character   1st Qu.:35.25   Class :character  
##  Median :187.50   Mode  :character   Median :43.00   Mode  :character  
##  Mean   :187.50                      Mean   :42.18                     
##  3rd Qu.:280.75                      3rd Qu.:50.00                     
##  Max.   :374.00                      Max.   :59.00                     
##  Sleep.Duration  Quality.of.Sleep Physical.Activity.Level  Stress.Level  
##  Min.   :5.800   Min.   :4.000    Min.   :30.00           Min.   :3.000  
##  1st Qu.:6.400   1st Qu.:6.000    1st Qu.:45.00           1st Qu.:4.000  
##  Median :7.200   Median :7.000    Median :60.00           Median :5.000  
##  Mean   :7.132   Mean   :7.313    Mean   :59.17           Mean   :5.385  
##  3rd Qu.:7.800   3rd Qu.:8.000    3rd Qu.:75.00           3rd Qu.:7.000  
##  Max.   :8.500   Max.   :9.000    Max.   :90.00           Max.   :8.000  
##  BMI.Category       Blood.Pressure       Heart.Rate     Daily.Steps   
##  Length:374         Length:374         Min.   :65.00   Min.   : 3000  
##  Class :character   Class :character   1st Qu.:68.00   1st Qu.: 5600  
##  Mode  :character   Mode  :character   Median :70.00   Median : 7000  
##                                        Mean   :70.17   Mean   : 6817  
##                                        3rd Qu.:72.00   3rd Qu.: 8000  
##                                        Max.   :86.00   Max.   :10000  
##  Sleep.Disorder    
##  Length:374        
##  Class :character  
##  Mode  :character  
##                    
##                    
## 

Visualisasi Nilai

Bar Chart Kualitas Tidur Berdasarkan Gender

qual.m <- subset(data[,c("Gender", "Quality.of.Sleep")], Gender == "Male")
qual.m <- qual.m[,"Quality.of.Sleep"]
qual.f <-subset(data[,c("Gender", "Quality.of.Sleep")], Gender == "Female")
qual.f <- qual.f[,"Quality.of.Sleep"]

category.qual.m <- table(qual.m)
category.qual.f <- table(qual.f)

dat.qual.m <- data.frame(value = (names(category.qual.m)), frequency = as.numeric(category.qual.m))

dat.qual.f <- data.frame(value = (names(category.qual.f)), frequency = as.numeric(category.qual.f))

dat.qual.m <- dat.qual.m[order(dat.qual.m$value), ]
dat.qual.f <- dat.qual.f[order(dat.qual.f$value), ]

data.qual <- data.frame(dat.qual.m , dat.qual.f[,"frequency"])
colnames(data.qual) <- c("Quality of Sleep", "Male", "Female")

dat.qual <- melt(data.qual, id.vars = "Quality of Sleep")
dat.qual <- ddply(dat.qual, "`Quality of Sleep`", transform, prop = value / sum(value))
dat.qualfix <- dat.qual[,-2]
ggplot(data = dat.qualfix, aes(x = `Quality of Sleep`, y = value, fill = variable)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.9)) +
  theme(axis.text.x = element_text(size = 8, hjust = 1)) +
  labs(
    title = "Quality of Sleep by Genders",
    y = "Frequency",
    x = "Quality"
  ) +
  geom_text(aes(label = paste(round(value, 1)), color = variable), position = position_dodge(width = 0.9), size = 3, vjust = -0.5) +
  scale_fill_manual(values = c("Female" = "#f44369", "Male" = "#3e3b92"), name = "Gender") +
  scale_color_manual(values = c("Female" = "#f44369", "Male" = "#3e3b92")) +
  guides(color = FALSE)
## Warning: The `<scale>` argument of `guides()` cannot be `FALSE`. Use "none" instead as
## of ggplot2 3.3.4.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

Berdasarkan grafik di atas, diperoleh informasi bahwa :

- Terdapat 69 wanita dan 2 pria yang memiliki kualitas tidur dengan skala 9 dari 10

- Terdapat 36 wanita dan 73 pria yang memiliki kualitas tidur dengan skala 8 dari 10

- Terdapat 37 wanita dan 40 pria yang memiliki kualitas tidur dengan skala 7 dari 10

- Terdapat 37 wanita dan 68 pria yang memiliki kualitas tidur dengan skala 6 dari 10

- Terdapat 4 wanita dan 3 pria yang memiliki kualitas tidur dengan skala 5 dari 10

- Terdapat 2 wanita dan 3 pria yang memiliki kualitas tidur dengan skala 4 dari 10

Secara keseluruhan, frekuensi wanita paling tinggi pada kualitas tidur berskala 9 sementara terendah di angka 4. Sementara itu, frekuensi pria paling tinggi pada kualitas tidur berskala 8 sedangkan yang terendah di angka 9. Frekuensi wanita cenderung stabil - tinggi di skala 6-9, sementara pria cenderung stabil - tinggi di skala 6-8.

Bar Chart Tingkat Stress Berdasarkan Gender

stress.m <- subset(data[,c("Gender", "Stress.Level")], Gender == "Male")
stress.m <- stress.m[,"Stress.Level"]
stress.f <-subset(data[,c("Gender", "Stress.Level")], Gender == "Female")
stress.f <- stress.f[,"Stress.Level"]

category.stress.m <- table(stress.m)
category.stress.f <- table(stress.f)

dat.stress.m <- data.frame(value = (names(category.stress.m)), frequency = as.numeric(category.stress.m))

dat.stress.f <- data.frame(value = (names(category.stress.f)), frequency = as.numeric(category.stress.f))

dat.stress.m <- dat.stress.m [order(dat.stress.m$value), ]
dat.stress.f <- dat.stress.f [order(dat.stress.f$value), ]

data.stress <- data.frame(dat.stress.m, dat.stress.f[,"frequency"])
colnames(data.stress) <- c("StressLevel", "Male", "Female")

dat.stress <- melt(data.stress, id.vars = "StressLevel")
dat.stress <- ddply(dat.stress, "StressLevel", transform, prop = value / sum(value))
library(ggplot2)
library(ggtext)
## Warning: package 'ggtext' was built under R version 4.3.3
ggplot(data.stress, aes(x = StressLevel)) +
  geom_bar(aes(y = Male), stat = "identity", fill = "#66a3ff", position = "dodge") +  
  geom_bar(aes(y = -Female), stat = "identity", fill = "#ff6999", position = "dodge") +  
  geom_text(aes(y = Male, label = Male), vjust = 0.5, hjust = -0.4, color = "#66a3ff", size = 3, position = position_dodge(width = 0.9)) +
  geom_text(aes(y = -Female, label = Female), vjust = 0.5, hjust = 1.4, color = "#ff6999", size = 3, position = position_dodge(width = 0.9)) +
  labs(title = "Bar Chart of Stress Level",
       subtitle = "<span style='color:#ff6999'>Female</span>  <span style='color:#66a3ff'>Male</span>",
       x = "Stress Level",
       y = "Frequency") +
  theme_minimal() +
  coord_flip() +
  theme(plot.margin = margin(0, 20, 0, 0, "pt"),  # Adjust the left margin here
        axis.title.x = element_text(size = 10, margin = margin(t = 10)),
        axis.title.y = element_text(size = 10, margin = margin(r = 10)),
        plot.subtitle = element_markdown(hjust = 0.5))

Berdasarkan grafik di atas, diperoleh informasi bahwa :

- Terdapat 34 wanita dan 36 pria yang memiliki tingkat stress dengan skala 8 dari 10

- Terdapat 12 wanita dan 38 pria yang memiliki tingkat stress dengan skala 7 dari 10

- Terdapat 9 wanita dan 37 pria yang memiliki tingkat stress dengan skala 6 dari 10

- Terdapat 2 wanita dan 65 pria yang memiliki tingkat stress dengan skala 5 dari 10

- Terdapat 61 wanita dan 9 pria yang memiliki tingkat stress dengan skala 4 dari 10

- Terdapat 67 wanita dan 4 pria yang memiliki tingkat stress dengan skala 3 dari 10

Berdasarkan grafik tersebut, diperoleh informasi bahwa tingkat stress pria lebih tinggi dibandingkan wanita. Antara pria dan wanita tidak sama jumlahnya, tetapi secara keseluruhan dapat dilihat bahwa kebanyakan pria memiliki tingkat stress pada skala 6-8, sementara wanita kebanyakan pada skala 3-4.

Visualisasi Sebaran

data3 <- data.frame(data$Gender, data$Sleep.Duration)
data3.m <- subset(data3, data.Gender == "Male")
data3.f <- subset(data3, data.Gender == "Female")

data3.f[186:189,] <- c("Female", NULL)
data3 <- data.frame(data3.m, data3.f)
data3 <- data3[, -c(1,3)]
colnames(data3) <- c("Male", "Female")
data3$Female <- as.numeric(data3$Female)
## Warning: NAs introduced by coercion
data3 <- data3[-(186:189),]

Density Plot Sebaran Data Durasi Tidur Antar Gender

ggplot(data3)+
  geom_density(aes(x=`Male`,fill= "Male" ),color="#e9ecef", alpha=0.4)+
  geom_density(aes(x=`Female`,fill= "Female" ),color="#e9ecef", alpha=0.4)+
  labs(title="Density Plot Sebaran Data Durasi Tidur")+
  xlab("Durasi Tidur")+
  ylab("density")+
  xlim(5,9.3)

Berdasarkan Density Plot di atas, diperoleh informasi bahwa sebaran data durasi tidur pria cenderung tinggi pada kisaran interval 5.8 - 6.5 dan 7 - 8, sementara wanita pada kisaran interval 5.8 - 7.3 dan 7.8 - 8.6. Puncak grafik menandakan bahwa peluang observasi data pada interval (x) tersebut cukup tinggi, menandakan juga bahwa sebaran data cukup pekat dalam interval tersebut.

Violin-Box Plot Durasi Tidur

data3 <- data.frame(data$Gender, data$Sleep.Duration)
data3.m <- subset(data3, data.Gender == "Male")
data3.f <- subset(data3, data.Gender == "Female")

data3.f[186:189,] <- c("Female", NULL)
data3 <- data.frame(data3.f, data3.m)
data3 <- data3[, -c(1,3)]
colnames(data3) <- c("Female", "Male")
data3$Female <- as.numeric(data3$Female)
## Warning: NAs introduced by coercion
Obs <- as.character(c(1:nrow(data3)))
data3 <- data.frame(Obs, data3)
data3melt <- melt(data3,id.vars = "Obs")

datasleep <- data3melt[,2:3]
datasleep <- datasleep[-c(186:189),]
colnames(datasleep) <- c("Gender", "Value")

reordatsleep <- reorder(datasleep$Gender, datasleep$Value, FUN = median)
ggplot(datasleep,aes(reordatsleep,Value))+
  geom_violin(aes(col = Gender), fill = "white", width = 0.7)+
  geom_boxplot(width=.1, fill= "#4B5768", outlier.colour=NA)+
  geom_jitter(alpha = 0.5, aes(color = Gender))+
  labs(x = NULL, y = "Sleep Duration")+
  theme(legend.position = "top")+
  stat_summary(fun=median,geom="point",fill="blue",shape=21,size=2.5) +
  scale_x_discrete(limits = rev(levels(reordatsleep))) + 
  coord_flip()+
  labs(title = "Violin-Box Plot of Sleep Duration")

Grafik di atas adalah violin plot dengan boxplot di dalamnya. Dalam plot tersebut, terlihat bagaimana sebaran data dari durasi tidur pria dan wanita.

Tampak bahwa sebaran data wanita cenderung tinggi pada kisaran interval 8 - 8.5 dan 6 - 7.3, ditunjukkan oleh padatnya titik dan badan violin plot yang besar. Pada kisaran interval 7.4 - 7.8 badan violin plot menyempit, menandakan bahwa sedikitnya data di interval tersebut. Dari boxplot juga terlihat bahwa sebaran cenderung menjulur ke kanan (jambang kanan lebih panjang) dan mediannya terletak di kisaran angka 7.2. Tidak ada titik yang terlihat menyimpang jauh dari boxplot dan violin plot, sehingga tidak terdeteksi adanya outlier.

Tampak bahwa sebaran data pria cenderung tinggi pada kisaran interval 6 - 6.5, ditunjukkan oleh padatnya titik dan badan violin plot yang besar. Pada kisaran interval 6.6 - 7 badan violin plot menyempit, menandakan bahwa sedikitnya data di interval tersebut. Dari boxplot juga terlihat bahwa sebaran cenderung menjulur ke kiri (jambang kiri lebih panjang) dan mediannya terletak di kisaran angka 7.2, sama seperti wanita. Tidak ada titik yang terlihat menyimpang jauh dari boxplot dan violin plot, sehingga tidak terdeteksi adanya outlier.

Histogram Durasi Tidur

avgsleep<-ddply(datasleep, "Gender", summarise, avg=mean(Value))

ggplot(datasleep, aes(x=Value, color=Gender)) +
  geom_histogram(fill="white")+
  geom_vline(data=avgsleep, aes(xintercept=avg, color=Gender),
             linetype="dashed")+
  theme(legend.position="right")+
  labs(y = "Frequency", x = "Sleep Duration") +
  geom_text(data = avgsleep, aes(x = avg-0.07, y = 37, label = paste(round(avg,1))), vjust = -1, size = 2.2)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Berdasarkan histogram tersebut, diperoleh informasi bahwa sebaran data durasi tidur wanita cenderung tinggi pada interval 6.0 - 7.2, dengan rata-rata sebesar 7.2. Di sisi lain, data durasi tidur pria cenderung tinggi dan meningkat pada interval 7.0 - 8.0, dengan rata-rata sebesar 7. Itu berarti, durasi tidur wanita cenderung menjulur ke kanan, sementara durasi tidur pria cenderung menjulur ke kiri. Di sini tidak terdeteksi juga adanya outlier karena tidak terlihat data yang menyimpang jauh.

Visualisasi Proporsi

Stacked Bar Chart Proporsi Gender Berdasarkan Kualitas Tidur

# Plot
ggplot(dat.qual, aes(x = `Quality of Sleep`, y = prop, fill = variable)) +
  geom_bar(stat = "identity") +
  scale_y_continuous(labels = scales::percent_format()) +
  labs(x = "Quality of Sleep", y = "Proportion", fill = "Group") +
  ggtitle("Stacked Bar Chart of Gender by Quality of Sleep Proportions") +
  theme_minimal()+
  theme(plot.margin = margin(0, 5, 0, 0, "pt"),
        axis.title.x = element_text(size = 10, margin = margin(t = 10)),
        axis.title.y = element_text(size = 10, margin = margin(r = 10)))+
  scale_fill_manual(values = ("variable" = c("#66b3ff", "#ff9999")))+
  coord_flip()

Dari stacked bar chart tersebut, terlihat bagaimana perbandingan gender berdasarkan kualitas tidurnya secara proporsional. Terlihat bahwa proporsi wanita sangat mendominasi pada angka 9, menandakan bahwa banyak wanita yang memiliki kualitas tidur di angka 9. Untuk proporsi pada skala lain bisa dilihat pada grafik tersebut, yang mana proporsi pria cenderung mendominasi wanita, sehingga dapat dikatakan kualitas tidur pria berada di bawah skala 9 dari 10.

Pie-Donut Chart Proporsi Gender Berdasarkan Kualitas Tidur

Pie-Donut chart berikut adalah gabungan pie chart dengan donut chart untuk 2 faktor yang memperlihatkan proporsi dari gender berdasarkan kualitas tidur

library(webr)
## Warning: package 'webr' was built under R version 4.3.3
dat.qualfix <- dat.qual[,-2]
qualfix <- dat.qualfix
colnames(qualfix) <- c("SleepQuality", "Gender", "value", "prop")
qualfix <- qualfix[-c(1:4,11:12),]
donut_chart <- PieDonut(qualfix, aes(SleepQuality,Gender ,count= value), title = "Donut Chart Quality of Sleep by Gender",labelposition=1)

Pie-Donut di atas hanya menunjukkan kualitas tidur dengan skala di sekitar rata-rata dari kedua gender, yakni 6, 7, dan 8. Dari chart di atas diperoleh informasi bahwa:

  1. Proporsi responden dengan kualitas tidur berskala 8 lebih besar daripada skala 6, kemudian diikuti oleh skala 7 di posisi terakhir.
  2. Proporsi pria tertinggi tampak pada kualitas tidur berskala 8 dengan proporsi sebesar 67%, sementara yang terendah pada skala 7 dengan proporsi sebesar 51.9%
  3. Proporsi wanita tertinggi tampak pada kualitas tidur berskala 7 dengan proporsi sebesar 48.1%, sementara yang terendah pada skala 8 dengan proporsi sebesar 33%, berkebalikan dengan data pria.

Treemap Proporsi Pekerjaan Berdasarkan Gender

Treemap berikut menunjukkan bagaimana sebaran dan proporsi dari pekerjaan responden pada data berdasarkan gender. Ukuran kotak menunjukkan besar kecilnya proporsi pada setiap kelompok pekerjaan maupun gender.

occ.m <- subset(data[,c("Gender", "Occupation")], Gender == "Male")
occ.m <- occ.m[,"Occupation"]
occ.f <-subset(data[,c("Gender", "Occupation")], Gender == "Female")
occ.f <- occ.f[,"Occupation"]

category.occ.m <- table(occ.m)
category.occ.f <- table(occ.f)

dat.occ.m <- data.frame(value = (names(category.occ.m)), frequency = as.numeric(category.occ.m))
dat.occ.m <- rbind(data.frame (value = c("Nurse", "Scientist", "Manager"), frequency = c(0,0,0)), dat.occ.m)
dat.occ.f <- data.frame(value = (names(category.occ.f)), frequency = as.numeric(category.occ.f))
dat.occ.f <- rbind(data.frame (value = c("Sales Representative", "Salesperson", "Software Engineer"), frequency = c(0,0,0)), dat.occ.f)

dat.occ.m <- dat.occ.m[order(dat.occ.m$value), ]
dat.occ.f <- dat.occ.f[order(dat.occ.f$value), ]

data.occ <- data.frame(dat.occ.m , dat.occ.f[,"frequency"])
colnames(data.occ) <- c("Occupation", "Male", "Female")
dat.occ.melt <- melt(data.occ, id.vars = "Occupation")
dat.occ.melt <- ddply(dat.occ.melt, "Occupation", transform, prop = value / sum(value))

library(treemap)
## Warning: package 'treemap' was built under R version 4.3.3
library(ggplot2)
library(treemapify)
## Warning: package 'treemapify' was built under R version 4.3.3
data_comb <- dat.occ.melt[,c("Occupation", "variable", "value")]
data_comb$Occupation <- as.character(data_comb$Occupation)
data_comb$variable <- as.character(data_comb$variable)
data_comb$Position <- ifelse(data_comb$variable == "Male", "Left", "Right")

# Plot treemap
ggplot(data_comb, aes(area = value, fill = variable, 
                       label = Occupation, subgroup = Position)) +
  geom_treemap() +
  geom_treemap_text(
    aes(label = paste(Occupation)), 
    color = "white",
    size = 15,
    place = "middle"
  ) +
  labs(title = "Treemap of Occupations by Gender") +
  theme(legend.position = "bottom") +
  scale_fill_manual(values = c("#ff9999", "#66b3ff")) +
  theme(legend.title = element_blank())

Berdasarkan Treemap Proporsi diatas, terlihat bahwa kotak biru mewakili pria dan merah mewakili wanita.

  1. Berdasarkan gender (warna), ukuran kotak merah dan biru secara keseluruhan terlihat relatif sama, menandakan bahwa proporsi frekuensi wanita dan pria dalam kategori pekerjaan ini relatif sama.

  2. Jika dilihat berdasarkan pekerjaan, kotak terbesar di kategori pria adalah dokter. Dapat disimpulkan bahwa proporsi dokter adalah yang tertinggi pada kelompok pekerjaan dengan gender pria. Setelah dokter kemudian diikuti dengan proporsi yang lebih kecil yakni pengacara (lawyer), salesperson, insinyur (engineer), guru (teacher), software engineer, akuntan (accountant), dan kategori lainnya dengan proporsi kecil yang diwakili dengan kotak kecil kosong.

  3. Jika dilihat berdasarkan pekerjaan, kotak terbesar di kategori wanita adalah perawat (nurse). Dapat disimpulkan bahwa proporsi perawat adalah yang tertinggi pada kelompok pekerjaan dengan gender wanita. Setelah perawat kemudian diikuti dengan proporsi yang lebih kecil yakni akuntan (accountant) dan guru (teacher) yang relatif sama, kemudian insinyur (engineer), ilmuwan (scientist), dokter (doctor) dan pengacara (lawyer) dengan proporsi relatif sama, lalu terakhir terdapat kotak kosong kecil yang mewakili proporsi kategori lainnya.

  4. Secara keseluruhan, terlihat bahwa proporsi insinyur (engineer) pria relatif sama dengan wanita. Proporsi pengacara (lawyer) pria lebih tinggi dari wanita, proporsi dokter (doctor) pria lebih tinggi dari wanita, proporsi akuntan (accountant) pria lebih rendah dari wanita, dan proporsi guru (teacher) pria lebih rendah dari wanita.

  5. Terdapat beberapa kategori pekerjaan yang didominasi oleh salah satu gender (dalam artian pada kelompok gender lain proporsi kategori pekerjaan tersebut sangat kecil atau sama dengan nol).

  6. Pada kelompok pria, terdapat kategori pekerjaan salesperson dan software engineer yang proporsinya mendominasi wanita, menandakan bahwa pada kelompok wanita proporsi pekerjaan tersebut sangat kecil atau sama dengan nol.

  7. Pada kelompok wanita, terdapat kategori pekerjaan perawat(nurse) dan ilmuwan (scientist) yang proporsinya mendominasi pria, menandakan bahwa pada kelompok pria proporsi pekerjaan tersebut sangat kecil atau sama dengan nol.