Project 2 - Monthly Patient Visits

Author

Ozge Gundogan

Published

October 9, 2026

Introduction

In this project, I will analyze monthly patient visits across 10 community health clinics during 2025.

The original dataset is in wide format, where each clinic has one row and monthly patient visit counts are stored in separate columns. I will use R to transform the dataset into tidy format and then analyze how patient visits vary across clinics and months.

The goal of this project is to practice data tidying and transformation while exploring patterns in patient visits.

Original Dataset: https://brightspace.cuny.edu/d2l/le/1404182/discussions/threads/5822251/View

Planned Approach

First, I will import the CSV file into R and examine its structure to understand how the data is organized.

Next, I will use pivot_longer() from the tidyr package to transform the dataset from wide to long format. I will also rename the columns to make them easier to understand.

After tidying the data, I will check for missing values and data consistency. I will also identify the minimum and maximum monthly patient visits for each clinic and calculate summary statistics, including the mean, median, and standard deviation.

Finally, I will calculate total patient visits by clinic and by month. I will use a bar chart to compare clinics and a line chart to examine monthly changes throughout 2025.

Anticipated Challenges

One possible challenge is transforming the monthly columns into a single month column while keeping the correct clinic names and patient visit counts.

Another challenge is making sure that the months appear in chronological order rather than alphabetical order, especially in the monthly visualization.

Code Base

Required Packages

I will use three R packages for this project. The tidyr package will help me transform the dataset from wide to long format. I will use dplyr to clean the data and calculate summary statistics. Finally, I will use ggplot2 to create charts and visualize patterns in monthly patient visits.

Code
library(tidyr)
library(dplyr)
library(ggplot2)

Data Source and Import

I will import the Monthly Patient Visits dataset from my GitHub repository using the read.csv2() function. I will keep the original column names and display the first six rows to examine how the data is organized.

Data Source: https://brightspace.cuny.edu/d2l/le/1404182/discussions/threads/5822251/View

Code
data_url <- "https://raw.githubusercontent.com/OzgeG01/DATA607-Assignment/refs/heads/main/monthly_patient_visits.csv"

patient_raw <- read.csv2(data_url, check.names = FALSE)

knitr::kable(head(patient_raw))
Clinic Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
Harbor Community Health Center 245 231 260 278 290 301 315 309 287 295 310 325
Riverside Family Health Clinic 190 205 198 220 235 241 250 263 255 270 268 280
Central Community Health Center 310 298 325 340 355 348 370 365 380 392 401 415
Eastside Family Clinic 155 162 170 168 180 195 201 210 205 218 225 230
Westview Community Health Center 270 265 280 295 310 320 318 330 342 350 360 375
Northside Health Clinic 225 218 240 251 260 272 280 275 290 298 305 315

Data Structure Before Tidying

Before tidying the dataset, I will use str() to examine the column names and data types. This will help me understand the structure of the original wide-format dataset.

Code
str(patient_raw)
'data.frame':   10 obs. of  13 variables:
 $ Clinic: chr  "Harbor Community Health Center" "Riverside Family Health Clinic" "Central Community Health Center" "Eastside Family Clinic" ...
 $ Jan   : int  245 190 310 155 270 225 180 290 205 165
 $ Feb   : int  231 205 298 162 265 218 175 282 212 170
 $ Mar   : int  260 198 325 170 280 240 192 300 220 182
 $ Apr   : int  278 220 340 168 295 251 205 315 230 190
 $ May   : int  290 235 355 180 310 260 215 325 242 198
 $ Jun   : int  301 241 348 195 320 272 220 340 250 205
 $ Jul   : int  315 250 370 201 318 280 230 350 245 215
 $ Aug   : int  309 263 365 210 330 275 238 345 260 220
 $ Sep   : int  287 255 380 205 342 290 242 360 268 228
 $ Oct   : int  295 270 392 218 350 298 250 372 275 235
 $ Nov   : int  310 268 401 225 360 305 255 380 285 240
 $ Dec   : int  325 280 415 230 375 315 265 395 292 250

The dataset contains 10 observations and 13 variables. The Clinic column contains clinic names as character values, while the 12 monthly columns (Jan to Dec) contain patient visit counts as integers. Each row represents one clinic. The data is currently in wide format because monthly visits are stored in separate columns.

Renaming Variables

I will rename the Clinic column to ClinicName to make the variable name more descriptive. I will keep the monthly column names unchanged because they are already clear and easy to understand.

Code
patient_renamed <- patient_raw %>%
  rename(
    ClinicName = Clinic
  )

knitr::kable(head(patient_renamed))
ClinicName Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
Harbor Community Health Center 245 231 260 278 290 301 315 309 287 295 310 325
Riverside Family Health Clinic 190 205 198 220 235 241 250 263 255 270 268 280
Central Community Health Center 310 298 325 340 355 348 370 365 380 392 401 415
Eastside Family Clinic 155 162 170 168 180 195 201 210 205 218 225 230
Westview Community Health Center 270 265 280 295 310 320 318 330 342 350 360 375
Northside Health Clinic 225 218 240 251 260 272 280 275 290 298 305 315

Transforming Data from Wide to Long Format

I will use pivot_longer() from the tidyr package to transform the dataset from wide to long format. The 12 monthly columns will be combined into two columns: Month and PatientVisits. The ClinicName column will remain unchanged. Each row will represent the number of patient visits for one clinic in one month.

Code
patient_long <- patient_renamed %>%
  pivot_longer(
    cols = Jan:Dec,
    names_to = "Month",
    values_to = "PatientVisits"
  )

head(patient_long)
# A tibble: 6 × 3
  ClinicName                     Month PatientVisits
  <chr>                          <chr>         <int>
1 Harbor Community Health Center Jan             245
2 Harbor Community Health Center Feb             231
3 Harbor Community Health Center Mar             260
4 Harbor Community Health Center Apr             278
5 Harbor Community Health Center May             290
6 Harbor Community Health Center Jun             301

Missing Values

After transforming the dataset into long format, I will check for missing values in each column. This will help me determine whether any clinic names, months, or patient visit counts are missing before continuing with the analysis.

Code
patient_long %>%
  summarise(
    ClinicNameMissing = sum(is.na(ClinicName)),
    MonthMissing = sum(is.na(Month)),
    PatientVisitsMissing = sum(is.na(PatientVisits))
  )
# A tibble: 1 × 3
  ClinicNameMissing MonthMissing PatientVisitsMissing
              <int>        <int>                <int>
1                 0            0                    0

The missing value check showed that there are no missing values in the ClinicName, Month, or PatientVisits columns. Therefore, no rows need to be removed or modified due to missing data.

Checking Unusual Values

I will check the PatientVisits column for unusual values, such as negative numbers or decimal values. Since patient visits represent counts, all values should be non-negative whole numbers. This check will help me identify any potential data inconsistencies before continuing with the analysis.

Code
patient_long %>%
  summarise(
    NegativeValues = sum(PatientVisits < 0),
    NonIntegerValues = sum(PatientVisits %% 1 != 0)
  )
# A tibble: 1 × 2
  NegativeValues NonIntegerValues
           <int>            <int>
1              0                0

The results show that there are no negative or decimal values in the PatientVisits column. All patient visit counts are non-negative whole numbers. Therefore, no corrections are needed for these values, and the dataset is ready for further analysis.

Summary Statistics

After checking the data for missing and unusual values, I will calculate summary statistics for monthly patient visits. I will calculate the number of observations, mean, median, minimum, maximum, and standard deviation for each clinic. These statistics will help me compare patient visit counts across clinics and identify differences in their monthly activity.

Code
patient_summary <- patient_long %>%
  group_by(ClinicName) %>%
  summarise(
    Count = n(),
    Mean = round(mean(PatientVisits), 2),
    Median = median(PatientVisits),
    Min = min(PatientVisits),
    Max = max(PatientVisits),
    SD = round(sd(PatientVisits), 2),
    .groups = "drop"
  )

knitr::kable(patient_summary)
ClinicName Count Mean Median Min Max SD
Central Community Health Center 12 358.25 360.0 298 415 36.13
Eastside Family Clinic 12 193.25 198.0 155 230 25.67
Greenwood Family Health Center 12 222.25 225.0 175 265 29.63
Harbor Community Health Center 12 287.17 292.5 231 325 28.95
Hillcrest Community Clinic 12 208.17 210.0 165 250 27.82
Lakeside Community Clinic 12 337.83 342.5 282 395 36.22
Northside Health Clinic 12 269.08 273.5 218 315 31.11
Parkview Health Center 12 248.67 247.5 205 292 28.40
Riverside Family Health Clinic 12 239.58 245.5 190 280 30.23
Westview Community Health Center 12 317.92 319.0 265 375 35.56

The summary statistics show that Central Community Health Center had the highest average monthly patient visits (358.25), followed by Lakeside Community Clinic (337.83) and Westview Community Health Center (317.92). Eastside Family Clinic had the lowest monthly average (193.25). Each clinic had 12 monthly observations. The standard deviations ranged from 25.67 at Eastside Family Clinic to 36.22 at Lakeside Community Clinic, showing that monthly patient visits varied across clinics.

Total Patient Visits by Clinic

I will calculate the total number of patient visits for each clinic during 2025. I will group the data by clinic and sum the monthly patient visits. This will help me compare the overall patient volume across the 10 clinics and identify which clinics had the highest and lowest total visits.

Code
patient_clinic_totals <- patient_long %>%
  group_by(ClinicName) %>%
  summarise(
    TotalVisits = sum(PatientVisits),
    .groups = "drop"
  ) %>%
  arrange(desc(TotalVisits))

patient_clinic_totals
# A tibble: 10 × 2
   ClinicName                       TotalVisits
   <chr>                                  <int>
 1 Central Community Health Center         4299
 2 Lakeside Community Clinic               4054
 3 Westview Community Health Center        3815
 4 Harbor Community Health Center          3446
 5 Northside Health Clinic                 3229
 6 Parkview Health Center                  2984
 7 Riverside Family Health Clinic          2875
 8 Greenwood Family Health Center          2667
 9 Hillcrest Community Clinic              2498
10 Eastside Family Clinic                  2319

The results show that Central Community Health Center had the highest total number of patient visits in 2025, with 4,299 visits. Lakeside Community Clinic ranked second with 4,054 visits, followed by Westview Community Health Center with 3,815 visits. Eastside Family Clinic had the lowest total, with 2,319 visits. These results show differences in patient volume across the 10 clinics.

Total Patient Visits by Clinic Visualization

I will create a bar chart to compare the total number of patient visits across the 10 clinics in 2025. I will arrange the clinics from the highest to the lowest number of visits to make the differences easier to see.

Code
ggplot(patient_clinic_totals,
       aes(x = reorder(ClinicName, TotalVisits),
           y = TotalVisits)) +
  geom_col(fill = "steelblue") +
  coord_flip() +
  labs(
    title = "Total Patient Visits by Clinic in 2025",
    x = "Clinic",
    y = "Total Patient Visits"
  ) +
  theme_minimal()

The bar chart shows that Central Community Health Center had the highest total number of patient visits in 2025, with 4,299 visits. Lakeside Community Clinic followed with 4,054 visits. Eastside Family Clinic had the lowest total, with 2,319 visits. The chart makes it easier to compare patient volumes across the 10 clinics and shows that some clinics served considerably more patients than others.

Total Patient Visits by Month

I will calculate the total number of patient visits for each month in 2025 across all 10 clinics. I will group the data by month and sum the patient visits. I will also arrange the months in chronological order from January to December. This will help me identify which months had the highest and lowest patient visits.

Code
patient_monthly_totals <- patient_long %>%
  mutate(
    Month = factor(Month, levels = month.abb)
  ) %>%
  group_by(Month) %>%
  summarise(
    TotalVisits = sum(PatientVisits),
    .groups = "drop"
  )

patient_monthly_totals
# A tibble: 12 × 2
   Month TotalVisits
   <fct>       <int>
 1 Jan          2235
 2 Feb          2218
 3 Mar          2367
 4 Apr          2492
 5 May          2610
 6 Jun          2692
 7 Jul          2774
 8 Aug          2815
 9 Sep          2857
10 Oct          2955
11 Nov          3029
12 Dec          3142

The monthly totals show that patient visits generally increased throughout 2025. February had the lowest total with 2,218 visits, while December had the highest total with 3,142 visits. Patient visits increased from 2,235 in January to 3,142 in December. Although there was a small decrease in February, the overall trend shows increasing patient visits across the 10 clinics during the year.

Total Patient Visits by Month Visualization

I will create a line chart to visualize the total number of patient visits across all 10 clinics for each month in 2025. This chart will help me identify monthly trends and changes in patient volume.

Code
ggplot(patient_monthly_totals,
       aes(x = Month, y = TotalVisits, group = 1)) +
  geom_line(color = "steelblue", linewidth = 1) +
  geom_point(color = "steelblue", size = 2) +
  labs(
    title = "Monthly Patient Visits in 2025",
    x = "Month",
    y = "Total Patient Visits"
  ) +
  theme_minimal()

The line chart shows an overall upward trend in patient visits throughout 2025. Total visits decreased slightly from 2,235 in January to 2,218 in February, but increased steadily from March through December. December had the highest number of visits (3,142), while February had the lowest (2,218). This pattern shows that patient visits increased across the 10 clinics during the year.

Conclusion

In this project, I analyzed monthly patient visits across 10 community health clinics during 2025. I transformed the original dataset from wide to long format using pivot_longer() and checked for missing and unusual values. The dataset contained no missing values, negative counts, or decimal values, so no additional cleaning was needed.

The summary statistics showed differences in patient visits across clinics. Central Community Health Center had the highest total number of visits (4,299), while Eastside Family Clinic had the lowest (2,319).

The monthly analysis showed that patient visits generally increased throughout 2025. February had the lowest total with 2,218 visits, while December had the highest with 3,142 visits. The line chart showed a steady increase in visits from March through December.

Overall, this project helped me practice transforming wide data into tidy format and using summary statistics and visualizations to identify patterns. The results showed differences in patient volume across clinics and an overall increase in monthly visits during 2025.

Citation

I used ChatGPT (GPT-5.6 Luna), developed by OpenAI, to help me understand some of the functions I used in this assignment and to check my work.

OpenAI. (2026). ChatGPT (GPT-5.6 Luna) [Large language model]. [https://chatgpt.com/ Accessed October 9, 2026].

Video Explainer

Link: