1 SOAL 1

1.1 Buat data frame bernama nilai_raw secara manual di R berdasarkan Tabel 1.

nilai_raw <- data.frame(Nama = c("Andi", "Budi", "Citra", "Dewi", "Andi"),
                        Matematika = c(80, 90, NA, 75, 80),
                        Statistika = c(85, 88, 78,"-", 85),
                        Umur = c(21, 20, 22, 21, 21),
                        stringsAsFactors = FALSE)
nilai_raw
##    Nama Matematika Statistika Umur
## 1  Andi         80         85   21
## 2  Budi         90         88   20
## 3 Citra         NA         78   22
## 4  Dewi         75          -   21
## 5  Andi         80         85   21

1.2 Identifikasi nilai yang hilang pada dataset secara sistematis. Ubah tanda hubung (“-”) pada nilai Statistika milik Dewi menjadi nilai hilang standar R, yaitu NA.

nilai_raw$Statistika[nilai_raw$Statistika == "-"] <- NA
nilai_raw$Statistika <- as.numeric(nilai_raw$Statistika)

1.3 Lakukan imputasi terhadap nilai Statistika yang kosong menggunakan rata-rata nilai Statistika mahasiswa lainnya yang tersedia.

ratarata_stat <- mean(nilai_raw$Statistika, na.rm = TRUE)
nilai_raw$Statistika[is.na(nilai_raw$Statistika)] <- ratarata_stat

1.4 Buat kolom baru bernama Status_Umur menggunakan fungsi ifelse() dengan ketentuan: Dewasa jika umur ≥ 21 tahun; Muda jika umur < 21 tahun.

nilai_raw$Status_Umur <- ifelse(nilai_raw$Umur >= 21, "Dewasa", "Muda")
nilai_raw
##    Nama Matematika Statistika Umur Status_Umur
## 1  Andi         80         85   21      Dewasa
## 2  Budi         90         88   20        Muda
## 3 Citra         NA         78   22      Dewasa
## 4  Dewi         75         84   21      Dewasa
## 5  Andi         80         85   21      Dewasa

1.5 Identifikasi dan hapus baris pengamatan yang duplikat.

nilai_raw <- unique(nilai_raw)
nilai_raw
##    Nama Matematika Statistika Umur Status_Umur
## 1  Andi         80         85   21      Dewasa
## 2  Budi         90         88   20        Muda
## 3 Citra         NA         78   22      Dewasa
## 4  Dewi         75         84   21      Dewasa

1.6 Simpan dataset yang telah dibersihkan ke dalam file bernama nilai_bersih.csv.

write.csv(nilai_raw, file = "nilai_bersih.csv", row.names = FALSE)
getwd()
## [1] "C:/PRAKTIKUM PEMROGRAMAN"

2 SOAL 2

2.1 Buat data frame bernama profil secara manual di R berdasarkan Tabel 2.

profil = data.frame(No = 1:10,
                    Gender = c("f","f","f","m","m","f","m","m","f","m"),
                    v1= c(8,15,8,14,8,10,9,9,10,12),
                    v2= c(9,8,13,9,2,6,9,10,13,10),
                    v3= c(5,9,12,8,9,10,7,8,6,9),
                    v4= c(9,5,6,"NA",16,9,13,10,7,8),
                    v5= c(9,10,7,11,8,10,9,5,10,17),
                    v6= c(9,8,9,10,10,10,12,10,12,7),
                    v7= c(5,10,14,6,8,9,10,6,13,9),
                    v8= c(9,12,12,11,9,7,9,12,9,10),
                    v9= c(11,9,12,11,8,7,11,6,6,7),
                    v10= c(8,15,9,8,9,11,7,8,9,7),
                    stringsAsFactors = FALSE)
profil
##    No Gender v1 v2 v3 v4 v5 v6 v7 v8 v9 v10
## 1   1      f  8  9  5  9  9  9  5  9 11   8
## 2   2      f 15  8  9  5 10  8 10 12  9  15
## 3   3      f  8 13 12  6  7  9 14 12 12   9
## 4   4      m 14  9  8 NA 11 10  6 11 11   8
## 5   5      m  8  2  9 16  8 10  8  9  8   9
## 6   6      f 10  6 10  9 10 10  9  7  7  11
## 7   7      m  9  9  7 13  9 12 10  9 11   7
## 8   8      m  9 10  8 10  5 10  6 12  6   8
## 9   9      f 10 13  6  7 10 12 13  9  6   9
## 10 10      m 12 10  9  8 17  7  9 10  7   7

2.2 Lakukan penyaringan (subsetting) sehingga hanya menyisakan pengamatan yang memenuhi salah satu kondisi berikut: gender laki-laki (m) dan v1 > 9 ; atau gender perempuan (f) dan v3 <= 10

myprofil <- ((profil$Gender == "m" & profil$v1>9)|(profil$Gender == "f" & profil$v3 <= 10))
profil_filter <- profil[myprofil,]
profil_filter
##    No Gender v1 v2 v3 v4 v5 v6 v7 v8 v9 v10
## 1   1      f  8  9  5  9  9  9  5  9 11   8
## 2   2      f 15  8  9  5 10  8 10 12  9  15
## 4   4      m 14  9  8 NA 11 10  6 11 11   8
## 6   6      f 10  6 10  9 10 10  9  7  7  11
## 9   9      f 10 13  6  7 10 12 13  9  6   9
## 10 10      m 12 10  9  8 17  7  9 10  7   7

2.3 Urutkan data hasil penyaringan secara multikriteria, dengan ketentuan: gender diurutkan secara descending; untuk pengamatan dengan gender yang sama, v5 diurutkan secara ascending.

library(dplyr)
## 
## 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
profil_filter <- profil %>% arrange(desc(profil$Gender), profil$v5)

profil_filter
##    No Gender v1 v2 v3 v4 v5 v6 v7 v8 v9 v10
## 1   8      m  9 10  8 10  5 10  6 12  6   8
## 2   5      m  8  2  9 16  8 10  8  9  8   9
## 3   7      m  9  9  7 13  9 12 10  9 11   7
## 4   4      m 14  9  8 NA 11 10  6 11 11   8
## 5  10      m 12 10  9  8 17  7  9 10  7   7
## 6   3      f  8 13 12  6  7  9 14 12 12   9
## 7   1      f  8  9  5  9  9  9  5  9 11   8
## 8   2      f 15  8  9  5 10  8 10 12  9  15
## 9   6      f 10  6 10  9 10 10  9  7  7  11
## 10  9      f 10 13  6  7 10 12 13  9  6   9
write.csv(profil_filter, file = "profil_filter.csv", row.names = FALSE)
getwd()
## [1] "C:/PRAKTIKUM PEMROGRAMAN"

3 SOAL 3

3.1 Gabungkan df_sales dan df_info menggunakan fungsi merge() dengan metode Full Outer Join, sehingga seluruh toko dari kedua data frame tetap disertakan. Perhatikan bahwa nama variabel kunci pada kedua data frame berbeda, yaitu id_toko pada df_sales dan id pada df_info. Gunakan argumen penggabungan yang sesuai.

df_sales <- data.frame(
  id_toko = c("T1", "T2", "T3"),
  Minggu1 = c(120, 150, 95),
  Minggu2 = c(135, 140, 110)
)

df_info <- data.frame(
  id = c("T1", "T2", "T4"),
  Kota = c("Jakarta", "Bandung", "Surabaya")
)

df_merged <- merge(
  df_sales, 
  df_info, 
  by.x = "id_toko", 
  by.y = "id", 
  all = TRUE
)
df_merged
##   id_toko Minggu1 Minggu2     Kota
## 1      T1     120     135  Jakarta
## 2      T2     150     140  Bandung
## 3      T3      95     110     <NA>
## 4      T4      NA      NA Surabaya

3.2 Ubah struktur data hasil penggabungan dari format Wide menjadi Long, sehingga: Minggu1 dan Minggu2 digabung menjadi satu kolom bernama Waktu; nilai penjualan disimpan dalam satu kolom bernama Penjualan.

df_long <- reshape(
  df_merged,
  varying = c("Minggu1", "Minggu2"),
  v.names = "Penjualan",
  timevar = "Waktu",
  times = c("Minggu1", "Minggu2"),
  direction = "long")
df_long
##           id_toko     Kota   Waktu Penjualan id
## 1.Minggu1      T1  Jakarta Minggu1       120  1
## 2.Minggu1      T2  Bandung Minggu1       150  2
## 3.Minggu1      T3     <NA> Minggu1        95  3
## 4.Minggu1      T4 Surabaya Minggu1        NA  4
## 1.Minggu2      T1  Jakarta Minggu2       135  1
## 2.Minggu2      T2  Bandung Minggu2       140  2
## 3.Minggu2      T3     <NA> Minggu2       110  3
## 4.Minggu2      T4 Surabaya Minggu2        NA  4
write.csv(df_long, file = "penjualan_long.csv", row.names = FALSE)
getwd()
## [1] "C:/PRAKTIKUM PEMROGRAMAN"

4 SOAL 4

4.1 Kenali struktur dataset CO2 dan identifikasi peran peubah Plant, Type, Treatment, conc, dan uptake, kemudian buat grafik menggunakan base R untuk menunjukkan hubungan conc dan uptake dengan mengatur bentuk dan ukuran titik, warna, judul, label sumbu, serta rentang sumbu, lalu tambahkan minimal dua elemen grafik menggunakan points(), lines(), abline(), atau text().

CO2
##    Plant        Type  Treatment conc uptake
## 1    Qn1      Quebec nonchilled   95   16.0
## 2    Qn1      Quebec nonchilled  175   30.4
## 3    Qn1      Quebec nonchilled  250   34.8
## 4    Qn1      Quebec nonchilled  350   37.2
## 5    Qn1      Quebec nonchilled  500   35.3
## 6    Qn1      Quebec nonchilled  675   39.2
## 7    Qn1      Quebec nonchilled 1000   39.7
## 8    Qn2      Quebec nonchilled   95   13.6
## 9    Qn2      Quebec nonchilled  175   27.3
## 10   Qn2      Quebec nonchilled  250   37.1
## 11   Qn2      Quebec nonchilled  350   41.8
## 12   Qn2      Quebec nonchilled  500   40.6
## 13   Qn2      Quebec nonchilled  675   41.4
## 14   Qn2      Quebec nonchilled 1000   44.3
## 15   Qn3      Quebec nonchilled   95   16.2
## 16   Qn3      Quebec nonchilled  175   32.4
## 17   Qn3      Quebec nonchilled  250   40.3
## 18   Qn3      Quebec nonchilled  350   42.1
## 19   Qn3      Quebec nonchilled  500   42.9
## 20   Qn3      Quebec nonchilled  675   43.9
## 21   Qn3      Quebec nonchilled 1000   45.5
## 22   Qc1      Quebec    chilled   95   14.2
## 23   Qc1      Quebec    chilled  175   24.1
## 24   Qc1      Quebec    chilled  250   30.3
## 25   Qc1      Quebec    chilled  350   34.6
## 26   Qc1      Quebec    chilled  500   32.5
## 27   Qc1      Quebec    chilled  675   35.4
## 28   Qc1      Quebec    chilled 1000   38.7
## 29   Qc2      Quebec    chilled   95    9.3
## 30   Qc2      Quebec    chilled  175   27.3
## 31   Qc2      Quebec    chilled  250   35.0
## 32   Qc2      Quebec    chilled  350   38.8
## 33   Qc2      Quebec    chilled  500   38.6
## 34   Qc2      Quebec    chilled  675   37.5
## 35   Qc2      Quebec    chilled 1000   42.4
## 36   Qc3      Quebec    chilled   95   15.1
## 37   Qc3      Quebec    chilled  175   21.0
## 38   Qc3      Quebec    chilled  250   38.1
## 39   Qc3      Quebec    chilled  350   34.0
## 40   Qc3      Quebec    chilled  500   38.9
## 41   Qc3      Quebec    chilled  675   39.6
## 42   Qc3      Quebec    chilled 1000   41.4
## 43   Mn1 Mississippi nonchilled   95   10.6
## 44   Mn1 Mississippi nonchilled  175   19.2
## 45   Mn1 Mississippi nonchilled  250   26.2
## 46   Mn1 Mississippi nonchilled  350   30.0
## 47   Mn1 Mississippi nonchilled  500   30.9
## 48   Mn1 Mississippi nonchilled  675   32.4
## 49   Mn1 Mississippi nonchilled 1000   35.5
## 50   Mn2 Mississippi nonchilled   95   12.0
## 51   Mn2 Mississippi nonchilled  175   22.0
## 52   Mn2 Mississippi nonchilled  250   30.6
## 53   Mn2 Mississippi nonchilled  350   31.8
## 54   Mn2 Mississippi nonchilled  500   32.4
## 55   Mn2 Mississippi nonchilled  675   31.1
## 56   Mn2 Mississippi nonchilled 1000   31.5
## 57   Mn3 Mississippi nonchilled   95   11.3
## 58   Mn3 Mississippi nonchilled  175   19.4
## 59   Mn3 Mississippi nonchilled  250   25.8
## 60   Mn3 Mississippi nonchilled  350   27.9
## 61   Mn3 Mississippi nonchilled  500   28.5
## 62   Mn3 Mississippi nonchilled  675   28.1
## 63   Mn3 Mississippi nonchilled 1000   27.8
## 64   Mc1 Mississippi    chilled   95   10.5
## 65   Mc1 Mississippi    chilled  175   14.9
## 66   Mc1 Mississippi    chilled  250   18.1
## 67   Mc1 Mississippi    chilled  350   18.9
## 68   Mc1 Mississippi    chilled  500   19.5
## 69   Mc1 Mississippi    chilled  675   22.2
## 70   Mc1 Mississippi    chilled 1000   21.9
## 71   Mc2 Mississippi    chilled   95    7.7
## 72   Mc2 Mississippi    chilled  175   11.4
## 73   Mc2 Mississippi    chilled  250   12.3
## 74   Mc2 Mississippi    chilled  350   13.0
## 75   Mc2 Mississippi    chilled  500   12.5
## 76   Mc2 Mississippi    chilled  675   13.7
## 77   Mc2 Mississippi    chilled 1000   14.4
## 78   Mc3 Mississippi    chilled   95   10.6
## 79   Mc3 Mississippi    chilled  175   18.0
## 80   Mc3 Mississippi    chilled  250   17.9
## 81   Mc3 Mississippi    chilled  350   17.9
## 82   Mc3 Mississippi    chilled  500   17.9
## 83   Mc3 Mississippi    chilled  675   18.9
## 84   Mc3 Mississippi    chilled 1000   19.9
str(CO2)
## Classes 'nfnGroupedData', 'nfGroupedData', 'groupedData' and 'data.frame':   84 obs. of  5 variables:
##  $ Plant    : Ord.factor w/ 12 levels "Qn1"<"Qn2"<"Qn3"<..: 1 1 1 1 1 1 1 2 2 2 ...
##  $ Type     : Factor w/ 2 levels "Quebec","Mississippi": 1 1 1 1 1 1 1 1 1 1 ...
##  $ Treatment: Factor w/ 2 levels "nonchilled","chilled": 1 1 1 1 1 1 1 1 1 1 ...
##  $ conc     : num  95 175 250 350 500 675 1000 95 175 250 ...
##  $ uptake   : num  16 30.4 34.8 37.2 35.3 39.2 39.7 13.6 27.3 37.1 ...
##  - attr(*, "formula")=Class 'formula'  language uptake ~ conc | Plant
##   .. ..- attr(*, ".Environment")=<environment: R_EmptyEnv> 
##  - attr(*, "outer")=Class 'formula'  language ~Treatment * Type
##   .. ..- attr(*, ".Environment")=<environment: R_EmptyEnv> 
##  - attr(*, "labels")=List of 2
##   ..$ x: chr "Ambient carbon dioxide concentration"
##   ..$ y: chr "CO2 uptake rate"
##  - attr(*, "units")=List of 2
##   ..$ x: chr "(uL/L)"
##   ..$ y: chr "(umol/m^2 s)"
summary(CO2)
##      Plant             Type         Treatment       conc          uptake     
##  Qn1    : 7   Quebec     :42   nonchilled:42   Min.   :  95   Min.   : 7.70  
##  Qn2    : 7   Mississippi:42   chilled   :42   1st Qu.: 175   1st Qu.:17.90  
##  Qn3    : 7                                    Median : 350   Median :28.30  
##  Qc1    : 7                                    Mean   : 435   Mean   :27.21  
##  Qc3    : 7                                    3rd Qu.: 675   3rd Qu.:37.12  
##  Qc2    : 7                                    Max.   :1000   Max.   :45.50  
##  (Other):42
#Melihat hubungan conc dengan uptake
plot(
  CO2$conc, CO2$uptake,
  pch = 19,
  cex = 1.2,
  col = ifelse(CO2$Treatment == "chilled", "blue", "red"),
  main = "Hubungan Konsentrasi dan Penyerapan CO2",
  xlab = "Konsentrasi CO2 (conc)",
  ylab = "Penyerapan CO2 (uptake)",
  xlim = c(0, 1000),
  ylim = c(0, 50)
)

# Elemen Tambahan 1: Garis tren rata-rata (abline)
abline(h = mean(CO2$uptake), col = "darkgreen", lty = 2, lwd = 2)

# Elemen Tambahan 2: Teks penjelas (text)
text(x = 800, y = mean(CO2$uptake) + 2, labels = "Rata-rata Uptake", col = "darkgreen", cex = 0.9)

# Elemen Tambahan 3: Legenda
legend("bottomright", legend = c("Nonchilled", "Chilled"), col = c("red", "blue"), pch = 19)

4.2 Buat satu tampilan grafik berukuran 2 × 2 yang terdiri atas empat jenis visualisasi berbeda untuk mengeksplorasi conc, uptake, Type, dan Treatment; tentukan sendiri jenis grafik yang paling sesuai dan berikan judul yang jelas pada setiap grafik.

par(mfrow = c(2, 2))

# Grafik 1: Scatter Plot conc vs uptake
plot(CO2$conc, CO2$uptake, main = "Scatter Plot: conc vs uptake",
     xlab = "Konsentrasi CO2", ylab = "Uptake", col = "darkblue", pch = 16)

# Grafik 2: Boxplot uptake berdasarkan Type
boxplot(uptake ~ Type, data = CO2, main = "Boxplot: uptake berdasarkan Type",
        xlab = "Tipe Tanaman", ylab = "Uptake", col = c("orange", "lightgreen"))

# Grafik 3: Boxplot uptake berdasarkan Treatment
boxplot(uptake ~ Treatment, data = CO2, main = "Boxplot: uptake berdasarkan Treatment",
        xlab = "Perlakuan Suhu", ylab = "Uptake", col = c("lightblue", "pink"))

# Grafik 4: Histogram Distribusi uptake
hist(CO2$uptake, main = "Histogram: Distribusi Uptake",
     xlab = "Uptake", col = "purple", border = "white")

4.3 Gunakan qplot() untuk membuat visualisasi cepat hubungan conc dan uptake berdasarkan Treatment, kemudian buat kembali visualisasi tersebut menggunakan ggplot2 dengan memetakan Treatment dan Type ke atribut visual yang berbeda di dalam aes() serta menggunakan geom_* yang sesuai.

library(ggplot2)
qplot(x = conc, y = uptake, data = CO2, color = Treatment,
      geom = c("point", "smooth"),
      main = "Visualisasi Cepat dengan qplot()")
## Warning: `qplot()` was deprecated in ggplot2 3.4.0.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'

# Visualisasi Ulang dengan ggplot2 (Pemetaan Treatment dan Type)
p_base <- ggplot(CO2, aes(x = conc, y = uptake, color = Treatment, shape = Type)) +
  geom_point(size = 3, alpha = 0.8) +
  geom_smooth(method = "loess", se = FALSE)
p_base
## `geom_smooth()` using formula = 'y ~ x'

4.4 Kembangkan grafik ggplot2 tersebut dengan menambahkan minimal satu stat_, satu scale_, serta salah satu coord_*, kemudian lengkapi grafik menggunakan labs() dan theme() atau salah satu tema siap pakai agar grafik lebih informatif dan mudah dibaca.

library(ggplot2)

# Visualisasi Cepat dengan qplot()
qplot(x = conc, y = uptake, data = CO2, color = Treatment,
      geom = c("point", "smooth"),
      main = "Visualisasi Cepat dengan qplot()")
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'

# Visualisasi Ulang dengan ggplot2 (Pemetaan Treatment dan Type)
p_base <- ggplot(CO2, aes(x = conc, y = uptake, color = Treatment, shape = Type)) +
  geom_point(size = 3, alpha = 0.8) +
  geom_smooth(method = "loess", se = FALSE)
p_base
## `geom_smooth()` using formula = 'y ~ x'

4.5 Simpan grafik akhir menggunakan ggsave() dalam format PNG dengan nama co2_uptake_visualisasi.png, kemudian tuliskan interpretasi mengenai hubungan antara konsentrasi CO₂ dan uptake serta perbedaan pola yang terlihat berdasarkan Type dan Treatment.

# Pengembangan grafik lengkap
p_final <- ggplot(CO2, aes(x = conc, y = uptake, color = Treatment, shape = Type)) +
  geom_point(size = 2.5, alpha = 0.7) +
  
  # 1. stat_* : Menambahkan garis tren rata-rata smoothing
  stat_smooth(method = "loess", se = TRUE, size = 1) +
  
  # 2. scale_* : Menyesuaikan skala warna dan simbol
  scale_color_manual(values = c("nonchilled" = "#D95F02", "chilled" = "#7570B3")) +
  scale_shape_manual(values = c("Quebec" = 16, "Mississippi" = 17)) +
  scale_x_continuous(breaks = seq(0, 1000, by = 200)) +
  
  # 3. coord_* : Membatasi rentang koordinat sumbu
  coord_cartesian(xlim = c(80, 1000), ylim = c(5, 50)) +
  
  # 4. labs() : Menambahkan judul, subtitle, dan label
  labs(
    title = "Eksplorasi Penyerapan CO2 Pada Tanaman Gras",
    subtitle = "Dampak Konsentrasi CO2, Asal Tipe Tanaman, dan Perlakuan Suhu",
    x = expression(paste("Konsentrasi ", CO[2], " (", mu, "L/L)")),
    y = expression(paste("Tingkat Penyerapan/Uptake (", mu, "mol/", m^2, " sec)")),
    color = "Perlakuan",
    shape = "Asal Tipe",
    caption = "Sumber Data: R Built-in Dataset CO2"
  ) +
  
  # 5. theme() : Menggunakan tema siap pakai + kustomisasi tampilan
  theme_minimal(base_size = 12) +
  theme(
    plot.title = element_text(face = "bold", size = 14, hjust = 0.5),
    plot.subtitle = element_text(hjust = 0.5, color = "gray30"),
    legend.position = "top",
    panel.grid.minor = element_blank()
  )
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
# Tampilkan grafik
print(p_final)
## `geom_smooth()` using formula = 'y ~ x'

# Menyimpan grafik akhir menggunakan ggsave()
ggsave(
  filename = "co2_uptake_visualisasi.png",
  plot = p_final,
  width = 8,
  height = 6,
  dpi = 300
)
## `geom_smooth()` using formula = 'y ~ x'