# Lab 2-1 Working with Essential Data Types
# R CODE ONLY

# =========================
# Setup
# =========================
library(dplyr)
library(lubridate)
library(stringr)

# =========================
# Sample Dataset
# =========================
data <- data.frame(
  ID = 1:20,
  Age = c(25, 34, 45, 29, 38, 52, 31, 27, 41, 33,
          28, 39, 46, 32, 37, 44, 30, 35, 42, 26),
  
  Income = c(
    45000, 62000, 85000, 51000, 73000,
    95000, 58000, 49000, 78000, 64000,
    53000, 71000, 89000, 60000, 75000,
    82000, 56000, 67000, 80000, 48000
  ),
  
  Segment = c(
    "Budget", "Standard", "Premium", "Budget", "Standard",
    "Premium", "Standard", "Budget", "Premium", "Standard",
    "Budget", "Standard", "Premium", "Standard", "Standard",
    "Premium", "Budget", "Standard", "Premium", "Budget"
  ),
  
  Review = c(
    "Great product!", "Good value", "Excellent quality",
    "Not satisfied", "Amazing service", "Poor quality",
    "Perfect for me", "Overpriced", "Highly recommend",
    "Good experience", "Disappointed", "Great quality",
    "Excellent", "Fair price", "Good product",
    "Outstanding", "Not worth it", "Very satisfied",
    "Excellent service", "Good value"
  ),
  
  Purchase = as.Date(c(
    "2024-01-15", "2024-02-20", "2024-01-08", "2024-03-12",
    "2024-02-28", "2024-01-22", "2024-03-05", "2024-02-14",
    "2024-01-30", "2024-03-18", "2024-02-10", "2024-01-25",
    "2024-03-22", "2024-02-05", "2024-01-18", "2024-03-08",
    "2024-02-25", "2024-01-12", "2024-03-15", "2024-02-18"
  ))
)

str(data)
head(data)

# =========================
# Numeric Data Analysis
# =========================
print("=== NUMERIC DATA ANALYSIS ===")

summary(data[c("Age", "Income")])

print(paste("Age - Unique values:",
            length(unique(data$Age)),
            "(discrete)"))

print(paste("Income - Unique values:",
            length(unique(data$Income)),
            "(continuous)"))

print("Age distribution:")
hist(data$Age,
     main = "Age Distribution",
     breaks = 5)

print("Income quartiles:")
quantile(data$Income)

correlation <- cor(data$Age, data$Income)

print(paste("Age-Income correlation:",
            round(correlation, 3)))

age_outliers <- data$Age[
  data$Age > (mean(data$Age) + 2 * sd(data$Age)) |
    data$Age < (mean(data$Age) - 2 * sd(data$Age))
]

print(paste("Age outliers:",
            paste(age_outliers, collapse = ", ")))

data$AgeGroup <- cut(
  data$Age,
  breaks = c(0, 30, 45, 100),
  labels = c("Young", "Middle", "Senior")
)

print("Average income by age group:")

aggregate(
  Income ~ AgeGroup,
  data = data,
  FUN = mean
)

# =========================
# Categorical Data Analysis
# =========================
print("=== CATEGORICAL DATA ANALYSIS ===")

print("Customer Segment distribution:")

segment_table <- table(data$Segment)
print(segment_table)

print("Customer Segment percentages:")

segment_percent <- round(
  prop.table(segment_table) * 100,
  1
)

print(segment_percent)

data$Segment <- factor(
  data$Segment,
  levels = c("Budget", "Standard", "Premium"),
  ordered = TRUE
)

print("Ordered segments:")
levels(data$Segment)

print("Segment by Age Group:")

segment_age_table <- table(
  data$Segment,
  data$AgeGroup
)

print(segment_age_table)

chi_test <- chisq.test(segment_age_table)

print(paste("Chi-square p-value:",
            round(chi_test$p.value, 4)))

mode_segment <- names(
  sort(table(data$Segment), decreasing = TRUE)
)[1]

print(paste("Most common segment:",
            mode_segment))

# =========================
# One-Hot Encoding
# =========================
create_dummy_vars <- function(data, column) {
  
  categories <- unique(data[[column]])
  
  for(cat in categories) {
    
    data[[paste0(column, "_", cat)]] <-
      as.numeric(data[[column]] == cat)
  }
  
  return(data)
}

data_encoded <- create_dummy_vars(data, "Segment")

data_encoded[c(
  "Segment_Budget",
  "Segment_Standard",
  "Segment_Premium"
)][1:10, ]

# =========================
# Text Data Analysis
# =========================
print("=== TEXT DATA ANALYSIS ===")

data$ReviewLength <- nchar(data$Review)

data$WordCount <- str_count(
  data$Review,
  "\\S+"
)

print("Text statistics:")

print(paste(
  "Average review length:",
  round(mean(data$ReviewLength), 1),
  "characters"
))

print(paste(
  "Average word count:",
  round(mean(data$WordCount), 1),
  "words"
))

print(paste(
  "Shortest review:",
  min(data$ReviewLength),
  "characters"
))

print(paste(
  "Longest review:",
  max(data$ReviewLength),
  "characters"
))

print("Reviews containing 'excellent':")

excellent_reviews <- data$Review[
  grepl("excellent",
        data$Review,
        ignore.case = TRUE)
]

print(excellent_reviews)

all_words <- unlist(
  strsplit(
    tolower(data$Review),
    "\\s+"
  )
)

word_freq <- table(all_words)

print("Most common words:")
print(sort(word_freq, decreasing = TRUE)[1:10])

classify_sentiment <- function(text) {
  
  text_lower <- tolower(text)
  
  positive_words <- c(
    "great", "excellent", "amazing",
    "perfect", "good", "outstanding", "love"
  )
  
  negative_words <- c(
    "poor", "bad", "terrible",
    "awful", "disappointed",
    "overpriced", "not worth"
  )
  
  pos_count <- sum(
    sapply(
      positive_words,
      function(x) grepl(x, text_lower)
    )
  )
  
  neg_count <- sum(
    sapply(
      negative_words,
      function(x) grepl(x, text_lower)
    )
  )
  
  if(pos_count > neg_count) {
    return("Positive")
  }
  
  if(neg_count > pos_count) {
    return("Negative")
  }
  
  return("Neutral")
}

data$Sentiment <- sapply(
  data$Review,
  classify_sentiment
)

print("Sentiment distribution:")
print(table(data$Sentiment))

print("Sentiment by customer segment:")

sentiment_segment <- table(
  data$Segment,
  data$Sentiment
)

print(sentiment_segment)

# =========================
# Timestamp Data Analysis
# =========================
print("=== TIMESTAMP DATA ANALYSIS ===")

print("Purchase date range:")

print(paste(
  "Earliest purchase:",
  min(data$Purchase)
))

print(paste(
  "Most recent purchase:",
  max(data$Purchase)
))

print(paste(
  "Date span:",
  as.numeric(
    max(data$Purchase) - min(data$Purchase)
  ),
  "days"
))

data$Year <- year(data$Purchase)

data$Month <- month(
  data$Purchase,
  label = TRUE
)

data$Weekday <- weekdays(data$Purchase)

data$Quarter <- quarter(data$Purchase)

print("Purchases by month:")

month_table <- table(data$Month)
print(month_table)

print("Purchases by weekday:")

weekday_table <- table(data$Weekday)
print(weekday_table)

print("Purchases by quarter:")

quarter_table <- table(data$Quarter)
print(quarter_table)

current_date <- as.Date("2024-04-01")

data$DaysAgo <- as.numeric(
  current_date - data$Purchase
)

data$WeeksAgo <- data$DaysAgo / 7

print("Time since purchase statistics:")
print(summary(data$DaysAgo))

data$Recency <- cut(
  data$DaysAgo,
  breaks = c(0, 30, 60, 90, Inf),
  labels = c(
    "Recent",
    "Moderate",
    "Old",
    "Very Old"
  )
)

print("Customer recency distribution:")
print(table(data$Recency))

print("Average income by purchase month:")

income_by_month <- aggregate(
  Income ~ Month,
  data = data,
  FUN = mean
)

print(income_by_month)

monthly_purchases <- data %>%
  group_by(Year, Month) %>%
  summarise(
    Count = n(),
    AvgIncome = mean(Income),
    .groups = "drop"
  )

print("Monthly purchase summary:")
print(monthly_purchases)

# =========================
# Temporal Feature Engineering
# =========================
engineer_temporal_features <- function(data) {
  
  data <- data[
    order(data$ID, data$Purchase),
  ]
  
  data$PurchaseInterval <- NA
  
  for(customer in unique(data$ID)) {
    
    customer_data <- data[data$ID == customer, ]
    
    if(nrow(customer_data) > 1) {
      
      intervals <- diff(customer_data$Purchase)
      
      data$PurchaseInterval[
        data$ID == customer
      ][-1] <- as.numeric(intervals)
    }
  }
  
  data$IsWeekend <- weekdays(data$Purchase) %in%
    c("Saturday", "Sunday")
  
  data$IsMonthEnd <- day(data$Purchase) > 25
  
  data$IsQuarterEnd <- month(data$Purchase) %in%
    c(3, 6, 9, 12)
  
  data$MonthsSinceStart <-
    as.numeric(
      data$Purchase - min(data$Purchase)
    ) / 30.44
  
  return(data)
}

data_with_temporal <-
  engineer_temporal_features(data)

print("Temporal features created:")

print(
  names(data_with_temporal)[
    grepl(
      "Purchase|Weekend|Month|Quarter",
      names(data_with_temporal)
    )
  ]
)

print("Weekend purchase analysis:")

weekend_analysis <- aggregate(
  Income ~ IsWeekend,
  data = data_with_temporal,
  FUN = mean
)

print(weekend_analysis)

# =========================
# Practice Dataset
# =========================
practice <- data.frame(
  ID = 1:15,
  
  Age = c(
    22, 35, 41, 29, 33,
    27, 50, 38, 26, 44,
    31, 36, 28, 45, 39
  ),
  
  Income = c(
    42000, 68000, 79000, 52000, 61000,
    48000, 90000, 75000, 46000, 82000,
    57000, 66000, 50000, 85000, 72000
  ),
  
  Segment = c(
    "Budget", "Standard", "Premium",
    "Budget", "Standard", "Budget",
    "Premium", "Standard", "Budget",
    "Premium", "Standard", "Standard",
    "Budget", "Premium", "Standard"
  ),
  
  Review = c(
    "Great service", "Good value",
    "Excellent experience", "Not satisfied",
    "Very good", "Poor quality",
    "Outstanding product", "Fair price",
    "Amazing support", "Highly recommend",
    "Good experience", "Excellent service",
    "Okay product", "Perfect quality",
    "Good value"
  ),
  
  Purchase = as.Date(c(
    "2024-01-05", "2024-01-10", "2024-01-12",
    "2024-01-18", "2024-01-22", "2024-02-01",
    "2024-02-05", "2024-02-10", "2024-02-14",
    "2024-02-18", "2024-02-22", "2024-03-01",
    "2024-03-05", "2024-03-10", "2024-03-15"
  ))
)

str(practice)
head(practice)
