SYNTAX & CONTROL FLOW

PRAKTIKUM WEEK - 4


Student Photo
IDENTITY
NAMA MAHASISWA
NIM: 52250005
Student in Data Science Programming
IT PROGRAMMING DATA SCIENCE DATA SCIENCE PROGRAMMING
INSTITUT TEKNOLOGI
SAINS BANDUNG
ITSB

1. Introduction

Description

Practicum Week-4 focuses on understanding and implementing Syntax and Control Flow in Data Science programming using R. Two core competencies are developed in this session:

  • Mastering conditional statements (if, if-else, if-else if-else) for logic-based decision making in code.
  • Applying various loop structures (for, while, break, next) to process and analyze datasets iteratively.
if / else
Multi-level logic branching for decision making
for loop
Iterate over data collections with known count
while loop
Iterate until a dynamic condition is met
break
Immediately stop and exit the loop entirely
next
Skip current iteration, loop continues

2. Dataset

Dummy Employee Dataset

All practicum exercises use a fictional employee dataset consisting of 5 employees with the following attributes: ID, Name, Age, Salary, Position, and Performance rating.

# ============================================================
# DATASET: Dummy Employee Data
# ============================================================

employees <- data.frame(
  id          = 1:5,
  name        = c("Bagas", "Joan", "Alya", "Dwi", "Nabil"),
  age         = c(25, 30, 27, 35, 40),
  salary      = c(5000, 7000, 6500, 10000, 12000),
  position    = c("Staff", "Supervisor", "Staff", "Manager", "Director"),
  performance = c("Good", "Very Good", "Average", "Good", "Very Good"),
  stringsAsFactors = FALSE
)

print(employees)
  id  name age salary   position performance
1  1 Bagas  25   5000      Staff        Good
2  2  Joan  30   7000 Supervisor   Very Good
3  3  Alya  27   6500      Staff     Average
4  4   Dwi  35  10000    Manager        Good
5  5 Nabil  40  12000   Director   Very Good

Variable Description

  • id: Unique identification number for each employee.
  • name: Full name of the employee.
  • age: Age of the employee in years.
  • salary: Monthly salary in currency units.
  • position: Job title (Staff / Supervisor / Manager / Director).
  • performance: Performance rating (Average / Good / Very Good).

3. Conditional Statements

What are Conditional Statements?

Conditional statements allow a program to execute a specific block of code only when a given condition evaluates to TRUE. In R, the primary syntax forms are:

  • if (condition) { ... }
  • if (...) { ... } else { ... }
  • if (...) { ... } else if (...) { ... } else { ... }

3.1 Bonus Calculation

Task Requirements

Calculate each employee's bonus based on their performance rating:

  • Very Good — 20% of salary
  • Good — 10% of salary
  • Average — 5% of salary

Output format: Name: Bagas, Bonus: 500

# ============================================================
# 3.1 Conditional Statements: Bonus Calculation
# ============================================================


for (i in 1:nrow(employees)) {
  name        <- employees$name[i]
  salary      <- employees$salary[i]
  performance <- employees$performance[i]

  # if - else if - else: determine bonus percentage
  if (performance == "Very Good") {
    bonus_pct <- 0.20
  } else if (performance == "Good") {
    bonus_pct <- 0.10
  } else {                         # Average
    bonus_pct <- 0.05
  }

  bonus <- salary * bonus_pct
  cat(sprintf("Name: %-8s | Performance: %-10s | Bonus: %d\n",
              name, performance, as.integer(bonus)))
}
Name: Bagas    | Performance: Good       | Bonus: 500
Name: Joan     | Performance: Very Good  | Bonus: 1400
Name: Alya     | Performance: Average    | Bonus: 325
Name: Dwi      | Performance: Good       | Bonus: 1000
Name: Nabil    | Performance: Very Good  | Bonus: 2400
EXPECTED OUTPUT Name: Bagas | Performance: Good | Bonus: 500
Name: Joan | Performance: Very Good | Bonus: 1400
Name: Alya | Performance: Average | Bonus: 325
Name: Dwi | Performance: Good | Bonus: 1000
Name: Nabil | Performance: Very Good | Bonus: 2400
Interpretation The if-else if-else structure maps each performance value to a different bonus percentage tier. Employees with a Very Good rating (Joan and Nabil) receive the highest bonus at 20% of their salary, while employees rated Average (Alya) receive only 5%. This multi-level branching approach is highly efficient for rule-based data categorization and represents a fundamental pattern in data science programming logic.

3.2 Age-Based Classification

Task Requirements

Classify each employee into an experience level based on their age:

  • Age < 28 years — Junior
  • Age 28 to 37 years — Mid-level
  • Age >= 38 years — Senior
# ============================================================
# 3.2 Age-Based Employee Classification
# ============================================================


for (i in 1:nrow(employees)) {
  name     <- employees$name[i]
  age      <- employees$age[i]
  position <- employees$position[i]

  # Multi-level if-else for age classification
  if (age < 28) {
    level <- "Junior"
  } else if (age >= 28 & age <= 37) {
    level <- "Mid-level"
  } else {
    level <- "Senior"
  }

  cat(sprintf("Name: %-8s | Age: %2d | Position: %-12s | Level: %s\n",
              name, age, position, level))
}
Name: Bagas    | Age: 25 | Position: Staff        | Level: Junior
Name: Joan     | Age: 30 | Position: Supervisor   | Level: Mid-level
Name: Alya     | Age: 27 | Position: Staff        | Level: Junior
Name: Dwi      | Age: 35 | Position: Manager      | Level: Mid-level
Name: Nabil    | Age: 40 | Position: Director     | Level: Senior
Interpretation By using the logical AND operator (&), a range condition is defined for the Mid-level category. The classification results show Bagas and Alya as Junior, Joan and Dwi as Mid-level, and Nabil as Senior. This reflects a diverse experience distribution across the team and demonstrates how conditional statements can segment continuous numerical data into meaningful categorical groups.

4. Loops: For and While

Why Use Loops?

Loops allow a program to execute the same block of code repeatedly without writing duplicate code. This is essential in data analysis where every row of a dataset must be processed automatically. R provides two primary loop types:

  • for loop — used when the number of iterations is known or when traversing a data collection.
  • while loop — used when the stopping condition depends on a value that changes during runtime.

Both loop types work with break (stop loop entirely) and next (skip current iteration).

4.1 For Loop: Filter Employees with Salary > 6000

Task

Use a for loop to list all employees who have a salary greater than 6000.

EXPECTED OUTPUT Name: Joan, Salary: 7000
Name: Alya, Salary: 6500
Name: Dwi, Salary: 10000
Name: Nabil, Salary: 12000
# ============================================================
# 4.1 For Loop: List Employees with Salary > 6000
# ============================================================


count <- 0

for (i in 1:nrow(employees)) {
  if (employees$salary[i] > 6000) {
    count <- count + 1
    cat(sprintf("[%d] Name: %-8s | Salary: %d\n",
                count, employees$name[i], employees$salary[i]))
  }
}
[1] Name: Joan     | Salary: 7000
[2] Name: Alya     | Salary: 6500
[3] Name: Dwi      | Salary: 10000
[4] Name: Nabil    | Salary: 12000
cat(sprintf("\nTotal employees with salary above 6000: %d person(s)\n", count))

Total employees with salary above 6000: 4 person(s)
Interpretation The for loop traverses each row of the data frame sequentially. The embedded if condition acts as a filter, printing only rows where salary exceeds 6000. Out of 5 employees, 4 qualify: Joan (7000), Alya (6500), Dwi (10000), and Nabil (12000). The counter variable count adds a summary at the end, demonstrating how auxiliary variables can enrich loop output with aggregate information.

4.2 While Loop: Display Until “Manager” is Found

Task

Use a while loop to display employees one by one until a "Manager" position is found. When found, display a stop label and exit the loop.

EXPECTED OUTPUT Name: Bagas, Position: Staff
Name: Joan, Position: Supervisor
Name: Alya, Position: Staff
Name: Dwi, Position: Manager (Stop here)
# ============================================================
# 4.2 While Loop: Stop When Manager Position is Found
# ============================================================


index <- 1

while (index <= nrow(employees)) {
  name     <- employees$name[index]
  position <- employees$position[index]

  if (position == "Manager") {
    cat(sprintf("Name: %-8s | Position: %s (Stop here)\n", name, position))
    break
  } else {
    cat(sprintf("Name: %-8s | Position: %s\n", name, position))
  }

  index <- index + 1
}
Name: Bagas    | Position: Staff
Name: Joan     | Position: Supervisor
Name: Alya     | Position: Staff
Name: Dwi      | Position: Manager (Stop here)
cat(sprintf("\nLoop stopped at index: %d\n", index))

Loop stopped at index: 4
Interpretation The while loop requires manual index management — index must be initialized before the loop and incremented at each iteration. Without the increment, the loop would run infinitely. When the "Manager" position is detected at Dwi (index 4), break immediately exits the loop. The combination of while and break is ideal when the stopping point is not known in advance, making it more flexible than a fixed for loop in dynamic scenarios.

4.3 Break: Stop Loop When Salary > 10,000

Task

Use break to stop the loop when an employee with a salary above 10,000 is found. Display the reason for stopping.

EXPECTED OUTPUT Name: Bagas, Salary: 5000
Name: Joan, Salary: 7000
Name: Alya, Salary: 6500
Name: Dwi, Salary: 10000
(Stopped because Nabil has a salary above 10,000)
# ============================================================
# 4.3 For Loop with Break: Stop When Salary Exceeds 10,000
# ============================================================


for (i in 1:nrow(employees)) {
  name   <- employees$name[i]
  salary <- employees$salary[i]

  if (salary > 10000) {
    cat(sprintf("(Stopped because %s has a salary above 10,000)\n", name))
    break
  }

  cat(sprintf("Name: %-8s | Salary: %d\n", name, salary))
}
Name: Bagas    | Salary: 5000
Name: Joan     | Salary: 7000
Name: Alya     | Salary: 6500
Name: Dwi      | Salary: 10000
(Stopped because Nabil has a salary above 10,000)
Interpretation The break keyword stops loop execution immediately and permanently. Note that Dwi (salary = 10000) is still printed because 10000 is NOT strictly greater than 10000 (the condition uses >, not >=). The loop only stops when Nabil (12000 > 10000) is encountered. This distinction is critical: break exits the entire loop, while next only skips a single iteration and allows the loop to continue.

4.4 Next: Skip Employees with “Average” Performance

Task

Use next (equivalent to continue in Python) to skip any employee with an "Average" performance rating while continuing to process all other employees normally.

EXPECTED OUTPUT Name: Bagas, Performance: Good
Name: Joan, Performance: Very Good
(Alya is skipped because the performance is "Average")
Name: Dwi, Performance: Good
Name: Nabil, Performance: Very Good
# ============================================================
# 4.4 For Loop with Next: Skip "Average" Performance Employees
# ============================================================


skipped_employees <- c()

for (i in 1:nrow(employees)) {
  name        <- employees$name[i]
  performance <- employees$performance[i]

  if (performance == "Average") {
    skipped_employees <- c(skipped_employees, name)
    cat(sprintf("(%s is skipped because the performance is \"Average\")\n", name))
    next
  }

  cat(sprintf("Name: %-8s | Performance: %s\n", name, performance))
}
Name: Bagas    | Performance: Good
Name: Joan     | Performance: Very Good
(Alya is skipped because the performance is "Average")
Name: Dwi      | Performance: Good
Name: Nabil    | Performance: Very Good
cat(sprintf("\nTotal skipped employees: %d (%s)\n",
            length(skipped_employees),
            paste(skipped_employees, collapse = ", ")))

Total skipped employees: 1 (Alya)
Interpretation In R, next is the equivalent of continue in Python. It skips the remainder of the current iteration and jumps directly to the next one. The key difference from break: next skips only one iteration while break exits the entire loop. Alya (Average) is bypassed, but the loop continues processing Dwi and Nabil. The skipped_employees vector records all bypassed names, providing a useful summary at the end of the loop.

5. Advanced Case Study

5.1 Combining Conditional + Loop: Full HR Report

Advanced Task

Create a comprehensive HR report that combines conditional statements and loops to produce a complete per-employee summary — including bonus amount, age-level classification, and an HR action recommendation — all in a single loop pass.

# ============================================================
# 5.1 Comprehensive HR Report
# ============================================================


for (i in 1:nrow(employees)) {
  name        <- employees$name[i]
  age         <- employees$age[i]
  salary      <- employees$salary[i]
  position    <- employees$position[i]
  performance <- employees$performance[i]

  # --- Bonus Calculation ---
  if (performance == "Very Good") {
    bonus_pct <- 0.20
  } else if (performance == "Good") {
    bonus_pct <- 0.10
  } else {
    bonus_pct <- 0.05
  }
  bonus <- as.integer(salary * bonus_pct)

  # --- Age Level Classification ---
  if (age < 28) {
    level <- "Junior"
  } else if (age >= 28 & age <= 37) {
    level <- "Mid-level"
  } else {
    level <- "Senior"
  }

  # --- HR Recommendation ---
  if (performance == "Very Good" & salary < 10000) {
    recommendation <- "Consider salary increase"
  } else if (performance == "Average") {
    recommendation <- "Enroll in training program"
  } else if (position == "Staff" & performance == "Good") {
    recommendation <- "Candidate for promotion"
  } else {
    recommendation <- "Maintain current performance"
  }

  # --- Print Report ---
  cat(sprintf("[%d] %s\n", i, name))
  cat(sprintf("    Age           : %d years (%s)\n", age, level))
  cat(sprintf("    Position      : %s\n", position))
  cat(sprintf("    Salary        : %d | Bonus: %d (%.0f%%)\n",
              salary, bonus, bonus_pct * 100))
  cat(sprintf("    Performance   : %s\n", performance))
  cat(sprintf("    Recommendation: %s\n\n", recommendation))
}
[1] Bagas
    Age           : 25 years (Junior)
    Position      : Staff
    Salary        : 5000 | Bonus: 500 (10%)
    Performance   : Good
    Recommendation: Candidate for promotion

[2] Joan
    Age           : 30 years (Mid-level)
    Position      : Supervisor
    Salary        : 7000 | Bonus: 1400 (20%)
    Performance   : Very Good
    Recommendation: Consider salary increase

[3] Alya
    Age           : 27 years (Junior)
    Position      : Staff
    Salary        : 6500 | Bonus: 325 (5%)
    Performance   : Average
    Recommendation: Enroll in training program

[4] Dwi
    Age           : 35 years (Mid-level)
    Position      : Manager
    Salary        : 10000 | Bonus: 1000 (10%)
    Performance   : Good
    Recommendation: Maintain current performance

[5] Nabil
    Age           : 40 years (Senior)
    Position      : Director
    Salary        : 12000 | Bonus: 2400 (20%)
    Performance   : Very Good
    Recommendation: Maintain current performance
Interpretation This advanced case demonstrates the power of nested conditional statements inside a for loop. Three independent conditional blocks run in parallel within a single iteration: bonus calculation, age-level classification, and HR recommendation. The recommendation logic uses the compound AND operator (&) for multi-condition rules — for example, an employee rated Very Good but with a low salary is flagged for a raise, while an Average performer is directed to a training program. This pattern represents how data analysts build automated, rule-based analysis pipelines in real-world HR applications.

5.2 While Loop: Salary Growth Simulation

Scenario

Simulate Bagas's salary increasing by 10% per period using a while loop until the salary reaches or exceeds the target of 8,000. Display the progress at each period.

# ============================================================
# 5.2 While Loop: Salary Growth Simulation for Bagas
# ============================================================


current_salary <- employees$salary[employees$name == "Bagas"]
target_salary  <- 8000
period         <- 0

cat(sprintf("Starting salary : %d\n", current_salary))
Starting salary : 5000
cat(sprintf("Target salary   : %d\n\n", target_salary))
Target salary   : 8000
while (current_salary < target_salary) {
  period         <- period + 1
  current_salary <- current_salary * 1.10

  if (current_salary >= target_salary) {
    cat(sprintf("Period %d: Salary = %.0f  --> Target achieved!\n",
                period, current_salary))
  } else {
    remaining <- target_salary - current_salary
    cat(sprintf("Period %d: Salary = %.0f  (%.0f remaining to target)\n",
                period, current_salary, remaining))
  }
}
Period 1: Salary = 5500  (2500 remaining to target)
Period 2: Salary = 6050  (1950 remaining to target)
Period 3: Salary = 6655  (1345 remaining to target)
Period 4: Salary = 7321  (679 remaining to target)
Period 5: Salary = 8053  --> Target achieved!
cat(sprintf("\nConclusion: %d period(s) needed to reach target salary of %.0f\n",
            period, current_salary))

Conclusion: 5 period(s) needed to reach target salary of 8053
Interpretation The while loop is ideal for this simulation because the number of iterations is not known at the start. The loop continues running as current_salary is multiplied by 1.10 each period. A nested if-else inside the loop provides informative feedback at each step, showing the remaining distance to the target. This pattern is commonly applied in financial forecasting, salary projection models, and iterative optimization workflows in data science.

6. Data Visualization with ggplot2

Why Visualize Control Flow Results?

Visualizing the output of conditional statements and loops transforms raw printed results into meaningful, interpretable charts. In this section, we apply ggplot2 to produce five distinct visualization types — each derived directly from the employee dataset and control flow logic developed in previous sections.

  • Bar Chart — compare salary across employees
  • Grouped Bar Chart — compare bonus by performance tier
  • Pie Chart — show distribution of experience levels
  • Line Chart — simulate salary growth over time
  • Scatter Plot — explore age vs salary relationship

6.1 Bar Chart: Employee Salary Comparison

Objective

Visualize each employee's monthly salary as a horizontal bar chart, sorted from highest to lowest, with salary values labeled directly on each bar. This directly reflects the dataset used throughout the practicum.

# ============================================================
# 6.1 Bar Chart: Monthly Salary per Employee
# ============================================================
library(ggplot2)
library(dplyr)

# Sort employees by salary descending
emp_sorted <- employees %>%
  arrange(desc(salary)) %>%
  mutate(name = factor(name, levels = name))

ggplot(emp_sorted, aes(x = name, y = salary, fill = salary)) +
  geom_col(width = 0.65, show.legend = FALSE) +
  geom_text(aes(label = paste0("IDR ", format(salary, big.mark = ","))),
            hjust = -0.1, fontface = "bold", size = 4, color = "#1A3C1B") +
  scale_fill_gradient(low = "#A5D6A7", high = "#1B5E20") +
  scale_y_continuous(expand = expansion(mult = c(0, 0.20)),
                     labels = scales::comma) +
  coord_flip() +
  labs(
    title    = "Monthly Salary per Employee",
    subtitle = "Sorted from highest to lowest salary",
    x        = "Employee",
    y        = "Monthly Salary (IDR)",
    caption  = "Source: Dummy Employee Dataset — Practicum Week-4"
  ) +
  theme_minimal(base_size = 13) +
  theme(
    plot.title      = element_text(face = "bold", size = 16, color = "#1B5E20"),
    plot.subtitle   = element_text(color = "#4A6E4C", size = 11),
    axis.text       = element_text(face = "bold", color = "#1B2A1C"),
    panel.grid.major.y = element_blank(),
    panel.grid.minor   = element_blank(),
    plot.background    = element_rect(fill = "#F5FBF5", color = NA),
    panel.background   = element_rect(fill = "#F5FBF5", color = NA),
    plot.caption       = element_text(color = "#888888", size = 9)
  )

Interpretation The horizontal bar chart clearly shows a strong salary hierarchy across the five employees. Nabil (Director) earns the highest salary at IDR 12,000, followed by Dwi (Manager) at IDR 10,000. There is a notable salary gap between management-level positions (Manager and Director) and operational roles (Staff and Supervisor). Bagas and Alya, both holding Staff positions, earn the lowest salaries at IDR 5,000 and IDR 6,500 respectively. This visualization reinforces the conditional classification logic applied in Section 3, where salary tiers directly influence bonus allocation.

6.2 Grouped Bar Chart: Bonus by Performance Tier

Objective

Display each employee's salary alongside their calculated bonus, grouped by performance tier. This directly visualizes the if-else if-else bonus logic from Section 3.1.

# ============================================================
# 6.2 Grouped Bar Chart: Salary vs Bonus by Performance
# ============================================================
library(tidyr)

# Compute bonus using the same if-else logic
emp_bonus <- employees %>%
  mutate(
    bonus_pct = case_when(
      performance == "Very Good" ~ 0.20,
      performance == "Good"      ~ 0.10,
      TRUE                       ~ 0.05
    ),
    bonus = as.integer(salary * bonus_pct)
  ) %>%
  select(name, performance, salary, bonus) %>%
  pivot_longer(cols = c(salary, bonus), names_to = "type", values_to = "amount") %>%
  mutate(
    type = factor(type, levels = c("salary", "bonus"),
                  labels = c("Monthly Salary", "Bonus")),
    performance = factor(performance, levels = c("Very Good", "Good", "Average"))
  )

pal <- c("Monthly Salary" = "#66BB6A", "Bonus" = "#EF5350")

ggplot(emp_bonus, aes(x = name, y = amount, fill = type)) +
  geom_col(position = position_dodge(width = 0.7), width = 0.6) +
  geom_text(aes(label = format(amount, big.mark = ",")),
            position = position_dodge(width = 0.7),
            vjust = -0.5, size = 3.2, fontface = "bold", color = "#1A3C1B") +
  facet_wrap(~ performance, scales = "free_x", nrow = 1) +
  scale_fill_manual(values = pal) +
  scale_y_continuous(labels = scales::comma,
                     expand = expansion(mult = c(0, 0.15))) +
  labs(
    title    = "Salary vs Bonus by Performance Tier",
    subtitle = "Bonus calculated: Very Good = 20% | Good = 10% | Average = 5%",
    x        = "Employee", y = "Amount (IDR)", fill = NULL,
    caption  = "Source: Dummy Employee Dataset — Practicum Week-4"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title       = element_text(face = "bold", size = 15, color = "#AD1457"),
    plot.subtitle    = element_text(color = "#880E4F", size = 10),
    strip.text       = element_text(face = "bold", size = 11, color = "white"),
    strip.background = element_rect(fill = "#C2185B", color = NA),
    legend.position  = "top",
    panel.grid.minor = element_blank(),
    plot.background  = element_rect(fill = "#FFF5F7", color = NA),
    panel.background = element_rect(fill = "#FFF5F7", color = NA),
    plot.caption     = element_text(color = "#888888", size = 9)
  )

Interpretation The grouped bar chart clearly demonstrates how the if-else if-else bonus logic from Section 3.1 produces proportionally different outcomes. Employees in the Very Good tier (Joan and Nabil) receive bonuses of IDR 1,400 and IDR 2,400 respectively — the highest in absolute terms because their salary base is also higher. The Average tier (Alya) receives the smallest bonus at IDR 325, reflecting the 5% cap. The faceted design allows direct within-tier comparison, making it easy to see how salary magnitude amplifies the impact of bonus percentage differences.

6.3 Pie Chart: Distribution of Experience Levels

Objective

Visualize the proportion of employees in each experience level category (Junior, Mid-level, Senior) derived from the age-based classification logic in Section 3.2.

# ============================================================
# 6.3 Pie Chart: Experience Level Distribution
# ============================================================

emp_level <- employees %>%
  mutate(
    level = case_when(
      age < 28            ~ "Junior",
      age >= 28 & age <= 37 ~ "Mid-level",
      TRUE                ~ "Senior"
    )
  ) %>%
  count(level) %>%
  mutate(
    pct   = n / sum(n) * 100,
    label = paste0(level, "\n", n, " employee(s)\n(", round(pct), "%)")
  )

level_colors <- c("Junior" = "#81C784", "Mid-level" = "#4FC3F7", "Senior" = "#CE93D8")

ggplot(emp_level, aes(x = "", y = n, fill = level)) +
  geom_col(width = 1, color = "white", linewidth = 1.5) +
  coord_polar(theta = "y", start = 0) +
  geom_text(aes(label = label),
            position = position_stack(vjust = 0.5),
            fontface = "bold", size = 4.2, color = "#1A2A1C", lineheight = 1.3) +
  scale_fill_manual(values = level_colors) +
  labs(
    title    = "Employee Experience Level Distribution",
    subtitle = "Based on age-classification: Junior (<28) | Mid-level (28–37) | Senior (≥38)",
    fill     = "Level",
    caption  = "Source: Dummy Employee Dataset — Practicum Week-4"
  ) +
  theme_void(base_size = 13) +
  theme(
    plot.title      = element_text(face = "bold", size = 15, hjust = 0.5, color = "#4A148C"),
    plot.subtitle   = element_text(hjust = 0.5, color = "#6A1B9A", size = 10),
    legend.position = "right",
    legend.title    = element_text(face = "bold"),
    plot.background = element_rect(fill = "#FAF3FF", color = NA),
    plot.caption    = element_text(color = "#888888", size = 9, hjust = 0.5)
  )

Interpretation The pie chart reveals that the team has a balanced but skewed age distribution. The Junior category (age below 28) contains 2 employees — Bagas (25) and Alya (27) — representing 40% of the workforce. The Mid-level category (age 28–37) also holds 2 employees — Joan (30) and Dwi (35) — at 40%. Only Nabil (40) qualifies as Senior at 20%. This distribution suggests the organization is relatively young, with most staff in early-to-mid career phases. From an HR perspective, this creates succession planning opportunities where Junior employees can be groomed to fill future leadership roles.

6.4 Line Chart: Salary Growth Simulation

Objective

Visualize Bagas's salary growth trajectory over multiple periods using a while loop simulation (10% increase per period) until the target of IDR 8,000 is reached. This directly corresponds to Section 5.2.

# ============================================================
# 6.4 Line Chart: Salary Growth Simulation
# ============================================================

# Rebuild growth data using while loop
start_sal  <- employees$salary[employees$name == "Bagas"]
target_sal <- 8000
cur_sal    <- start_sal
period_num <- 0

growth_data <- data.frame(period = 0, salary = cur_sal, status = "Start")

while (cur_sal < target_sal) {
  period_num <- period_num + 1
  cur_sal    <- cur_sal * 1.10
  status     <- ifelse(cur_sal >= target_sal, "Target Achieved", "Growing")
  growth_data <- rbind(growth_data,
                       data.frame(period = period_num,
                                  salary = round(cur_sal),
                                  status = status))
}

growth_data$status <- factor(growth_data$status,
                              levels = c("Start", "Growing", "Target Achieved"))

ggplot(growth_data, aes(x = period, y = salary)) +
  geom_hline(yintercept = target_sal, linetype = "dashed",
             color = "#E53935", linewidth = 0.8, alpha = 0.7) +
  geom_line(color = "#2E7D32", linewidth = 1.8) +
  geom_point(aes(fill = status), shape = 21, size = 5,
             color = "white", stroke = 1.5) +
  geom_text(aes(label = format(salary, big.mark = ",")),
            vjust = -1.2, fontface = "bold", size = 3.8, color = "#1B5E20") +
  annotate("text", x = max(growth_data$period) * 0.05, y = target_sal + 180,
           label = "Target: IDR 8,000", color = "#E53935",
           fontface = "bold", size = 3.8, hjust = 0) +
  scale_fill_manual(values = c("Start" = "#FFF176",
                                "Growing" = "#81C784",
                                "Target Achieved" = "#EF5350")) +
  scale_x_continuous(breaks = growth_data$period) +
  scale_y_continuous(labels = scales::comma,
                     expand = expansion(mult = c(0.05, 0.15))) +
  labs(
    title    = "Salary Growth Simulation — Bagas (10% per Period)",
    subtitle = "While loop: salary increases 10% each period until reaching IDR 8,000",
    x        = "Period", y = "Salary (IDR)", fill = "Status",
    caption  = "Source: Dummy Employee Dataset — Practicum Week-4"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title      = element_text(face = "bold", size = 15, color = "#BF360C"),
    plot.subtitle   = element_text(color = "#E64A19", size = 10),
    legend.position = "top",
    panel.grid.minor = element_blank(),
    plot.background = element_rect(fill = "#FFF8F5", color = NA),
    panel.background = element_rect(fill = "#FFF8F5", color = NA),
    plot.caption    = element_text(color = "#888888", size = 9)
  )

Interpretation The line chart visualizes the while loop simulation from Section 5.2. Starting at IDR 5,000, Bagas's salary grows by 10% compounding each period. The growth curve shows an accelerating trajectory characteristic of percentage-based growth — each period adds a larger absolute amount than the last. The red dashed line marks the target of IDR 8,000. The simulation requires 5 periods to reach and surpass the target, with a final salary of approximately IDR 8,053. The color-coded points distinguish the starting point (yellow), intermediate growth (green), and the achievement milestone (red), making the progression immediately readable.

6.5 Scatter Plot: Age vs Salary Relationship

Objective

Explore the relationship between employee age and salary, with points colored by experience level and sized by bonus amount. A regression trend line is included to show the overall direction of the relationship.

# ============================================================
# 6.5 Scatter Plot: Age vs Salary with Trend Line
# ============================================================

emp_scatter <- employees %>%
  mutate(
    level = case_when(
      age < 28              ~ "Junior",
      age >= 28 & age <= 37 ~ "Mid-level",
      TRUE                  ~ "Senior"
    ),
    bonus = as.integer(salary * case_when(
      performance == "Very Good" ~ 0.20,
      performance == "Good"      ~ 0.10,
      TRUE                       ~ 0.05
    )),
    level = factor(level, levels = c("Junior", "Mid-level", "Senior"))
  )

level_cols <- c("Junior" = "#81C784", "Mid-level" = "#4FC3F7", "Senior" = "#CE93D8")

ggplot(emp_scatter, aes(x = age, y = salary)) +
  geom_smooth(method = "lm", se = TRUE, color = "#B0BEC5",
              fill = "#ECEFF1", linewidth = 1, alpha = 0.5) +
  geom_point(aes(fill = level, size = bonus), shape = 21,
             color = "white", stroke = 2, alpha = 0.95) +
  geom_text(aes(label = name), vjust = -1.5, fontface = "bold",
            size = 3.8, color = "#1A2A1C") +
  scale_fill_manual(values = level_cols) +
  scale_size_continuous(range = c(5, 14),
                        labels = scales::comma,
                        name   = "Bonus (IDR)") +
  scale_x_continuous(breaks = seq(24, 42, by = 2)) +
  scale_y_continuous(labels = scales::comma,
                     expand = expansion(mult = c(0.1, 0.15))) +
  labs(
    title    = "Age vs Salary — Employee Overview",
    subtitle = "Point size = bonus amount | Color = experience level | Line = linear trend",
    x        = "Age (years)", y = "Monthly Salary (IDR)",
    fill     = "Experience Level",
    caption  = "Source: Dummy Employee Dataset — Practicum Week-4"
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title      = element_text(face = "bold", size = 15, color = "#004D40"),
    plot.subtitle   = element_text(color = "#00695C", size = 10),
    legend.position = "right",
    panel.grid.minor = element_blank(),
    plot.background  = element_rect(fill = "#F0FFFE", color = NA),
    panel.background = element_rect(fill = "#F0FFFE", color = NA),
    plot.caption     = element_text(color = "#888888", size = 9)
  )

Interpretation The scatter plot reveals a strong positive correlation between age and salary — older employees consistently earn higher salaries, as confirmed by the upward-sloping linear trend line. This aligns with the experience-level classification from Section 3.2: Senior employee Nabil earns the most (IDR 12,000), while Junior employees Bagas and Alya earn less. The point sizes represent bonus amounts — Nabil's large bubble reflects his high absolute bonus (IDR 2,400) despite the same 20% rate as Joan. One notable exception is Alya, whose salary (IDR 6,500) is slightly above Joan's (IDR 7,000) would suggest, indicating factors beyond age influence compensation. The confidence band around the trend line widens at the extremes, reflecting the limited sample size of five employees.

7. Summary and Conclusion

Comparison Table: Control Flow Concepts in R

# ============================================================
# 7. Summary Table
# ============================================================

summary_df <- data.frame(
  Concept = c(
    "if / else if / else",
    "for loop",
    "while loop",
    "break",
    "next"
  ),
  "R Syntax" = c(
    "if (cond) {} else if (cond) {} else {}",
    "for (i in 1:n) { ... }",
    "while (condition) { ... }",
    "break",
    "next"
  ),
  "When to Use" = c(
    "Multi-level decisions based on data conditions",
    "Iteration over a collection with known size",
    "Iteration until a dynamic runtime condition is met",
    "Permanently and immediately stop the entire loop",
    "Skip current iteration, continue remaining ones"
  ),
  "Practicum Example" = c(
    "Calculate employee bonus by performance tier",
    "Filter employees with salary above 6000",
    "Iterate until Manager position is found",
    "Stop when salary exceeds 10,000",
    "Skip employees with Average performance"
  ),
  check.names = FALSE
)

print(summary_df)
              Concept                               R Syntax
1 if / else if / else if (cond) {} else if (cond) {} else {}
2            for loop                 for (i in 1:n) { ... }
3          while loop              while (condition) { ... }
4               break                                  break
5                next                                   next
                                         When to Use
1     Multi-level decisions based on data conditions
2        Iteration over a collection with known size
3 Iteration until a dynamic runtime condition is met
4   Permanently and immediately stop the entire loop
5    Skip current iteration, continue remaining ones
                             Practicum Example
1 Calculate employee bonus by performance tier
2      Filter employees with salary above 6000
3      Iterate until Manager position is found
4              Stop when salary exceeds 10,000
5      Skip employees with Average performance

Key Conclusions

Practicum Week-4 has successfully demonstrated the use of conditional statements, loop structures, and ggplot2 visualizations in R for structured data analysis. The following key points were established:

  1. if-else if-else enables efficient multi-tier data categorization, such as calculating bonuses by performance level or classifying employees by age group. The bar chart in Section 6.2 visually confirmed the proportional differences in bonus outcomes across tiers.
  2. for loop is the primary tool for processing every element in a data collection when the number of iterations is determined, such as traversing all rows in a data frame to filter high-salary employees.
  3. while loop is most appropriate when the stopping condition depends on a value that changes dynamically — demonstrated in the salary growth simulation (Section 5.2 and 6.4), where 5 periods were needed to reach the IDR 8,000 target.
  4. break provides full control to exit a loop immediately when a target condition is met, without completing remaining iterations.
  5. next (equivalent to continue in Python) allows irrelevant data records to be selectively bypassed while all other records are still processed normally.
  6. ggplot2 visualizations transformed control flow outputs into five interpretable chart types: bar chart (salary comparison), grouped bar (bonus by tier), pie chart (experience distribution), line chart (salary growth), and scatter plot (age–salary correlation), each revealing actionable HR insights.

The scatter plot (Section 6.5) confirmed a strong positive correlation between age and salary, while the pie chart (Section 6.3) showed a young workforce with 80% of employees in Junior or Mid-level categories — presenting significant growth and succession planning opportunities for the organization.