R: R Data Analysis Report

Last updated: 2026-08-26

This is the final lesson of the R tutorial—it brings together everything you’ve learned in the previous 29 lessons to create a complete end-to-end project. From reading data to cleaning it, performing exploratory data analysis (EDA), building models, visualizing results, and generating reports, this lesson simulates a typical day in the life of a data analyst.

After completing this lesson, you’ll be able to independently complete a full R data analysis project—at the level of a data science job interview portfolio.

1. What You'll Learn



2. A Day in the Life of a Data Analyst

(1) Pain Point: It takes 3 days to turn data into a report

Alice is a data analyst who has been assigned the task of analyzing customer behavior in 2024 and providing her manager with a comprehensive report.

Traditional process: Import Excel data → Clean the data → Create an Excel pivot table → Generate a chart → Copy to PowerPoint → Write the analysis → Manager requests to see it one week later.

(2) Solution using R

R
# 1. One line R Markdown Report
rmarkdown::render('customer_analysis.Rmd')

1 line of code → Complete HTML/PDF report (including code, results, charts, and analysis).



3. The 6 Stages of an End-to-End Project

100%
graph TB
    A[1. Data Loading] --> B[2. Data Cleaning]
    B --> C[3. EDA Explore]
    C --> D[4. Descriptive Statistics]
    D --> E[5. Modeling and Analysis]
    E --> F[6. Visualization and Reporting]

    A --> A1[readr/DBI]
    B --> B1[tidyr/stringr]
    C --> C1[skimr/GGally]
    D --> D1[dplyr summary]
    E --> E1[lm/glm]
    F --> F1[ggplot2/Rmd]

    style A fill:#fff3cd
    style B fill:#cce5ff
    style C fill:#d4edda
    style D fill:#f8d7da
    style E fill:#e1d4ff
    style F fill:#ffe1d4

(1) 6-Stage Goals

Phase Objective Output
1. Loading Data Reading Data tibble
2. Data Cleaning Handling Missing/Outlier/Duplicate Values Clean tibble
3. EDA Explore Distribution/Relationships Charts + Statistics
4. Descriptive Statistics Key Metrics Summary Table
5. Modeling Regression/Classification/Clustering Model Objects
6. Report Synthesis + Analysis HTML/PDF


4. Hands-On: End-to-End Customer Behavior Analysis Project

(1) Complete R script

R
# ============================================
# Customer Behavior Analysis - End-to-End Projects
# Stage: 1. Data Loading -> 6. Report Output
# ============================================

library(readr)
library(dplyr)
library(tidyr)
library(stringr)
library(lubridate)
library(ggplot2)
library(broom)
library(skimr)

# ========== Stage 1: Data Loading ==========
cat('=== Stage 1: Data Loading ===\n')

set.seed(42)
n <- 2000
customers_raw <- tibble(
  customer_id = 1:n,
  age = round(rnorm(n, 35, 12)),
  gender = sample(c('M', 'F'), n, replace = TRUE),
  city = sample(c('Beijing', 'Shanghai', 'Guangzhou', 'Shenzhen', 'Hangzhou'), n, replace = TRUE),
  register_date = sample(seq(as.Date('2023-01-01'),
                              as.Date('2024-06-30'), by = 'day'), n, replace = TRUE),
  monthly_visits = round(rnorm(n, 10, 5)),
  avg_order_value = round(rnorm(n, 200, 80)),
  support_calls = sample(0:10, n, replace = TRUE),
  plan = sample(c('Basics', 'Advanced', 'Company'), n, replace = TRUE,
                 prob = c(0.5, 0.3, 0.2))
) |>
  mutate(
    logit_p = -2 + 0.02 * age - 0.05 * monthly_visits + 0.2 * support_calls,
    p = 1 / (1 + exp(-logit_p)),
    churn = rbinom(n, 1, p)
  ) |>
  select(-logit_p, -p) |>
  mutate(
    age = ifelse(row_number() %in% sample(n, 10), NA, age),
    avg_order_value = ifelse(row_number() %in% sample(n, 5), -999, avg_order_value),
    register_date = ifelse(row_number() %in% sample(n, 8), NA, register_date)
  )

write_csv(customers_raw, 'customer_raw.csv')
cat('Loaded', nrow(customers_raw), 'Raw Data Row\n\n')

# ========== Stage 2: Data Cleaning ==========
cat('=== Stage 2: Data Cleaning ===\n')

customers <- customers_raw |>
  janitor::clean_names() |>
  distinct() |>
  mutate(
    age = ifelse(is.na(age) | age < 0 | age > 150,
                 median(age[age > 0 & age < 150], na.rm = TRUE), age),
    avg_order_value = ifelse(avg_order_value < 0, NA, avg_order_value)
  ) |>
  drop_na(register_date) |>
  filter(monthly_visits >= 0, support_calls >= 0)

cat('After cleaning:', nrow(customers), 'rows\n')
cat('  - Duplicates:', nrow(customers_raw) - nrow(distinct(customers_raw)), 'removed\n')
cat('  - Age Missing/Exception: Processed\n')
cat('  - Abnormal Order Amount: Set to NA\n\n')

# ========== Stage 3: EDA Explore ==========
cat('=== Stage 3: EDA Explore ===\n')

cat('Data Dimensions:', nrow(customers), 'rows x', ncol(customers), 'cols\n')
cat('Churn rate:', round(mean(customers$churn) * 100, 2), '%\n')

churn_by_plan <- customers |>
  group_by(plan) |>
  summarise(
    n = n(),
    churn_rate = round(mean(churn) * 100, 2),
    avg_age = round(mean(age), 1),
    avg_visits = round(mean(monthly_visits), 1)
  )
cat('\nChurn Rate by Plan Type:\n')
print(churn_by_plan)

p1 <- ggplot(customers, aes(x = monthly_visits, y = avg_order_value,
                            color = factor(churn))) +
  geom_point(alpha = 0.5) +
  geom_smooth(method = 'lm', se = FALSE) +
  scale_color_brewer(palette = 'Set1', labels = c('Not lost', 'Loss')) +
  labs(title = 'Number of visits vs Average Order Value',
       x = 'Monthly Visits', y = 'Average Order Value', color = 'Status') +
  theme_minimal()

cat('Generate 2 Key Charts\n\n')

# ========== Stage 4: Descriptive Statistics ==========
cat('=== Stage 4: Descriptive Statistics ===\n')

key_metrics <- customers |>
  summarise(
    Total Number of Customers = n(),
    Number of Lost Customers = sum(churn),
    Churn rate = round(mean(churn) * 100, 2),
    Average Age = round(mean(age), 1),
    Average Monthly Visits = round(mean(monthly_visits), 1),
    Average Order Value = round(mean(avg_order_value, na.rm = TRUE), 2),
    Average Number of Customer Service Inquiries = round(mean(support_calls), 1)
  )
print(key_metrics)

by_city <- customers |>
  group_by(city) |>
  summarise(
    Number of customers = n(),
    Churn rate = round(mean(churn) * 100, 2),
    Average Order = round(mean(avg_order_value, na.rm = TRUE), 2)
  ) |>
  arrange(desc(Number of customers))
cat('\nBy City:\n')
print(by_city)
cat('\n')

# ========== Stage 5: Modeling and Analysis ==========
cat('=== Stage 5: Modeling and Analysis ===\n')

# 5.1 Logistic Regression: Churn Prediction
churn_model <- glm(churn ~ age + gender + plan + monthly_visits +
                     avg_order_value + support_calls,
                   data = customers, family = binomial)
cat('Logistic Regression Model:\n')
summary(churn_model)

cat('\nOdds Ratio Analysis:\n')
or_df <- tidy(churn_model, conf.int = TRUE, exponentiate = TRUE) |>
  filter(term != '(Intercept)')
print(or_df |> select(term, estimate, std.error, p.value, conf.low, conf.high))

# 5.3 Linear Regression: Visits Forecast
visit_model <- lm(monthly_visits ~ age + plan + avg_order_value,
                   data = customers)
cat('\nVisits Forecast Model:\n')
summary(visit_model)

# 5.4 Model Evaluation
library(pROC)
customers$churn_prob <- predict(churn_model, type = 'response')
roc_obj <- roc(customers$churn, customers$churn_prob)
cat('\nChurn Model AUC:', round(auc(roc_obj), 3), '\n\n')

# ========== Stage 6: Visualization and Reporting ==========
cat('=== Stage 6: Visualization and Reporting ===\n')

p2 <- customers |>
  group_by(plan, churn) |>
  summarise(n = n(), .groups = 'drop') |>
  ggplot(aes(x = plan, y = n, fill = factor(churn))) +
  geom_col(position = 'fill') +
  scale_y_continuous(labels = scales::percent) +
  scale_fill_brewer(palette = 'Set1', labels = c('Not lost', 'Loss')) +
  labs(title = 'Churn Rates by Plan Type', x = 'Plan', y = 'Ratio', fill = 'Status') +
  theme_minimal()

p3 <- customers |>
  group_by(plan) |>
  summarise(
    n = n(),
    churn_rate = mean(churn)
  ) |>
  ggplot(aes(x = plan, y = churn_rate, fill = plan)) +
  geom_col() +
  geom_text(aes(label = paste0(round(churn_rate * 100, 1), '%')),
            vjust = -0.5) +
  scale_y_continuous(labels = scales::percent,
                     expand = expansion(mult = c(0, 0.15))) +
  labs(title = 'Churn Rates by Plan Type', x = 'Plan', y = 'Churn rate') +
  theme_minimal() +
  theme(legend.position = 'none')

p4 <- ggplot(customers, aes(x = plan, y = monthly_visits, fill = plan)) +
  geom_boxplot() +
  labs(title = 'Distribution of Monthly Visits by Plan', x = 'Plan', y = 'Monthly Visits') +
  theme_minimal() +
  theme(legend.position = 'none')

# 6.2 Save Chart
ggsave('chart_visits_vs_order.png', p1, width = 8, height = 6, dpi = 300)
ggsave('chart_churn_by_plan.png', p2, width = 8, height = 6, dpi = 300)
ggsave('chart_churn_rate.png', p3, width = 8, height = 6, dpi = 300)
ggsave('chart_visits_by_plan.png', p4, width = 8, height = 6, dpi = 300)

# 6.3 Save Model
saveRDS(churn_model, 'churn_model.rds')
saveRDS(visit_model, 'visit_model.rds')

# 6.4 Save the processed data
write_csv(customers, 'customer_clean.csv')
saveRDS(customers, 'customer_clean.rds')

# 6.5 Summary of Business Insights
cat('\n=== Summary of Business Insights ===\n')
cat('1. Overall attrition rate:', round(mean(customers$churn) * 100, 2), '%\n')
cat('2. Customers with >5 support calls churn rate:',
    round(mean(customers$churn[customers$support_calls > 5]) * 100, 2), '%\n')
cat('3. Customers with <5 monthly visits churn rate:',
    round(mean(customers$churn[customers$monthly_visits < 5]) * 100, 2), '%\n')
cat('4. The Basic Plan has the highest churn rate (',
    round(mean(customers$churn[customers$plan == 'Basics']) * 100, 2), '%)\n')
cat('5. Older age and fewer visits -> higher probability of attrition\n')
cat('6. Suggestion: Add customers with >5 support calls to the high-risk list, proactively retain\n')

cat('\n=== All Done ===\n')
cat('Output Files:\n')
cat('  - customer_raw.csv (Raw Data)\n')
cat('  - customer_clean.csv / .rds (Data After Cleaning)\n')
cat('  - chart_*.png (4 charts)\n')
cat('  - churn_model.rds (Churn Prediction Model)\n')
cat('  - visit_model.rds (Visits Forecast Model)\n')

(2) R Markdown Report Template (Simplified Version)

Create a new customer_report.Rmd file with the complete Rmd template structure (YAML + 6 sections + R code blocks + explanatory text):

YAML metadata (at the beginning of the file): define title / author / output format (html_document + theme: flatly + toc: true).

6 Main Chapters:

  1. Project Overview - A brief background introduction + 3 analysis objectives
  2. Data Overview - Load cleaned data + Skimr summary
  3. Exploratory Analysis - Churn Rate + Distribution by Plan + Scatter Plot
  4. Statistical Model - Load the saved churn_model.rds file and tidy it up to display OR
  5. Key Findings - bulleted list, 3–5 items OR interpretation
  6. Business Recommendations - 3 actionable recommendations + list of appendices

Each chapter is separated by R code blocks (```{r}) embedding analysis code, with ## 1. xxx / ## 2. xxx headings between sections.

💡 Tip: The complete Rmd template has been omitted (see the official RStudio R Markdown template generator for reference). The core consists of four elements: YAML metadata + ```{r} code blocks + #/## headings + explanatory text.

(3) Generate a report

R
# Generate HTML Report
rmarkdown::render('customer_report.Rmd',
                   output_format = 'html_document',
                   output_file = 'customer_report.html')

# Generate PDF Report (LaTeX installation required)
rmarkdown::render('customer_report.Rmd',
                   output_format = 'pdf_document',
                   output_file = 'customer_report.pdf')

Expected Output:



5. Complete Learning Path for R Tutorials

(1) 5 Stages

100%
graph TB
    A[Phase 1 Basics 10 lessons] --> B[Phase 2 Data 7 lessons]
    B --> C[Phase 3 Visualization 5 lessons]
    C --> D[Phase 4 Statistics 5 lessons]
    D --> E[Phase 5 Practical Application 3 lessons]
    E --> F[End Able to work independently on projects]

    style A fill:#cce5ff
    style B fill:#d4edda
    style C fill:#f8d7da
    style D fill:#e1d4ff
    style E fill:#ffe1d4
    style F fill:#fff3cd

(2) List of 30 Lessons

Phase Class Topic
1 Basics 01-10 Introduction to R / Basic Syntax / Data Types / Vectors / Operators / Control Flow / Functions / Matrices / Lists / Data Frames
2 Data 11-17 CSV / Excel / JSON / Database / String / Regular Expressions / Refactoring
3 Visualization 18–22 Basic Plotting / Introduction to ggplot2 / Advanced / Themes / Maps
4 Statistics 23–27 Descriptive Statistics / Probability Distributions / Hypothesis Testing / Linear Regression / Logistic Regression
5 Practical Exercises 28–30 EDA / Data Cleaning / Comprehensive Report


6. Suggestions for Further Study

(1) Advanced R Packages

Bag Purpose
Shiny Web Application (Interactive Dashboard)
plumber REST API (Machine Learning Deployment)
tidymodels Modern Machine Learning (caret alternative)
torch Deep Learning
arrow Big Data (Parquet files)

(2) Essential Resources

Resource Description
R for Data Science (2e) Hadley's official book, hadley/r4ds
Advanced R (2nd ed.) Advanced R Programming
ggplot2: Elegant Graphics ggplot2 principles book
R Markdown Cookbook Report Generation
RStudio Cheatsheets Quick Reference Cards

(3) Real-World Projects


❓ FAQ

Q How do I use R Markdown?
A Create a .Rmd file (YAML metadata + Markdown text + R code blocks). rmarkdown::render() Generate HTML/PDF. Use the RStudio "Knit" button to generate a report with a single click.
Q What is the difference between .rds and .RData?
A .rds files store a single object (such as a single model), while .RData files store multiple objects (such as an entire workspace). Using .rds is more standard practice in the new code.
Q How do I deploy a model to production?
A There are three ways: ① Use the Plumber package to write a REST API; ② Use the Vetiver package for standardized deployment; ③ Export to PMML or Python for calling.
Q How do I manage my projects?
A Use RStudio Project + the renv package (package management) + Git (version control) + the here package (path management).
Q What can I do after completing the 30 lessons?
A You’ll be able to independently complete 80% of data analysis tasks—including reading data, cleaning data, exploratory data analysis (EDA), statistics, modeling, visualization, and reporting. The remaining 20% (machine learning, deep learning, and big data) will require additional study.
Q What should I learn next?
A ① Machine Learning (tidymodels) ② Text Mining (tidytext) ③ Time Series (fable) ④ Shiny Dashboards ⑤ Advanced R Programming. Just choose one area to explore in depth.

📖 Summary



📝 Exercises

Graduation Project Assignment (Complete End-to-End Data Analysis Project, Final Project for R Tutorial Lesson 30):

  1. Data Selection: Select 1 public dataset (recommended: Titanic / Iris / mtcars / mpg / nycflights13)
  2. Complete Process:
    • Step 1: Read the data (using readr or datasets)
    • Phase 2: Cleaning (Missing/Anomalous/Duplicate/Type)
    • Phase 3: EDA (summary + skimr + visualization)
    • Phase 4: Descriptive Statistics (Aggregated by Group)
    • Step 5: Modeling (lm or glm)
    • Phase 6: Report (R Markdown HTML)
  3. Deliverables:
    • analysis.R Main script (200+ lines)
    • report.Rmd R Markdown report
    • 5+ charts
      1. Summary of Business Insights (500 characters)
  4. Grading Criteria:
    • The code runs (20 points)
    • Complete process (20 points)
    • Depth of Analysis (20 points)
    • Aesthetically pleasing charts (20 points)
    • Readability of the report (20 points) Completing the graduation project = Completing the R tutorial!

▶ Example: Summary of Lesson 30

R
# ============================================
# R Tutorial 30 Lesson Study Summary Script
# After running, it outputs the topic for each lesson
# ============================================

lessons <- c(
  "01 UnderstandingR", "02 Basic Grammar", "03 Data Types", "04 Vector",
  "05 Operators", "06 Control Flow", "07 Function", "08 Matrices and Arrays",
  "09 List", "10 Data Frames and Factors",
  "11 CSV", "12 Excel",   "13 JSON and XML", "14 Database",
  "15 String", "16 Regular", "17 Data Reimagined",
  "18 Basic Drawing", "19 ggplot2 Getting Started", "20 ggplot2 Advanced",
  "21 Theme Customization", "22 Map",
  "23 Descriptive Statistics", "24 Probability Distribution", "25 Hypothesis Testing",
  "26 Linear Regression", "27 Logistic Regression",
  "28 EDA", "29 Data Cleaning", "30 Comprehensive Report"
)

cat("R Tutorial 30 Course List:\n")
for (i in seq_along(lessons)) {
  cat(sprintf("%2d. %s\n", i, lessons[i]))
}
▶ Try it Yourself

Expected Output:

TEXT 📖 Display only
R Tutorial 30 Course List:
 1. 01 UnderstandingR
 2. 02 Basic Grammar
...
30. 30 Comprehensive Report


7. Congratulations on completing Lesson 30 of the R Tutorial

You’ve now systematically completed the 30 lessons in R Data Science—from basic syntax to end-to-end projects—and are ready to tackle real-world data analysis tasks on your own. Next up is hands-on practice—finding real data, working on real projects, and building your portfolio. We wish you every success in becoming an outstanding data scientist!

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏