Create a Gantt Chart Without Excel (feat. R & Lease Renewal)

It's not easy to keep track of the renewal and termination dates in the Residential Tenancy Act from text alone. You can use a Gantt chart in Excel, but there's an easier way. All you need to do is copy & paste the source code for the Gantt chart and run it.

In this post, we'll see how to use R to visualize a schedule of lease renewals and terminations. After signing a two-year lease on February 3, 2021, we'll use Implicit renewalsWe've also created a visual representation of when landlords and tenants should each give notice of non-renewal, so you can get a clearer picture of the important dates.

간트차트 엑셀없이 만드는 R 시각화 그림
(Result of creating a Gantt chart using R)

Create a Gantt Chart without Excel

Here's the lease schedule you want to visualize

  • February 3, 2021: Contract starts
  • February 2, 2023: End of contract
  • August 3, 2022 - December 2, 2022: When landlords/tenants must give notice of non-renewal
  • May 1, 2023: Tenant termination notice for cause after implied renewal
  • August 1, 2023: End of contract and release of security deposit

If you sign a 2-year worldwide lease on February 3, 2021, your landlord will be able to legally terminate your lease for cause before the end date (February 2, 2023). 6 monthsOn or before August 3, 2022, the contract end date 2 monthsLandlords and tenants must give notice of non-renewal between December 2, 2022, and the end of the lease if they need to move for personal reasons. 2 monthsDecember 2, 2022, to give notice of non-renewal.

In this situation, assuming the implied renewal extended the worldwide lease for two more years, if the tenant gives notice to terminate on May 1, 2023, the landlord would be required to return the security deposit on August 1, 2023, three months after receiving the notice.

Now, let's visualize this complex schedule using R.

R Code to Create Gantt Charts without Excel Explained

First, install and load the required packages.

if (!require(ggplot2)) install.packages("ggplot2")
if (!require(dplyr)) install.packages("dplyr")
library(ggplot2)
library(dplyr)

Create a data frame

Create a data frame for the data you want to visualize. Create a data frame with each time period and start and end dates.

df <- data.frame(
  Task = c("Initial Contract Term", "Landlord Notice Period", "Tenant Notice Period",
           "Renewal Contract Term", "3 months after notice"),
  Start = as.Date(c("2021-02-03", "2022-08-03", "2022-08-03",
                    "2023-02-03", "2023-05-01"))),
  End = as.Date(c("2023-02-02", "2022-12-02", "2022-12-02",
                  "2025-02-02", "2023-07-30"))),
  Section = c("Initial Contract", "Notice of Non-Renewal", "Notice of Non-Renewal",
              "Renewal Contract", "Contract Termination")
)

Create a significant date data frame

Create a data frame of important dates. The data frame you created above is for framing purposes, and the dates in it are what you need to show dotted lines and date labels in your chart.

important_dates <- as.Date(c("2021-02-03", "2023-02-02", "2022-08-03", "2022-12-02",
                             "2023-01-02", "2023-02-03", "2025-02-02",
                             "2023-05-01", "2023-08-01")))
important_dates <- sort(important_dates)

Improved date label repositioning function

Define a function to reposition the date labels so that they don't overlap each other. This is the tricky part, because if the date labels we want to display are too close together, they will overlap and be hard to see, so we implement a function that checks for dates that are within 7 days of each other and separates them up or down.

adjust_label_position <- function(dates) {
  n <- length(dates)
  positions <- rep(0, n)
  last_position <- 0
  for (i in 2:n) {
    if (as.numeric(dates[i] - dates[i-1]) <= 7) { # Check for closest dates within 7 days
      positions[i] <- (last_position + 1) %% 2 # alternate up and down based on previous position
      last_position <- positions[i]
    } else {
      last_position <- 0
    }
  }
  return(positions)
}

Adjust the date label position

Use the function defined above to adjust the date label position.

label_positions <- adjust_label_position(important_dates)

Create a date label data frame

Create a data frame with label positions.

date_labels <- data.frame(
  x = important_dates,
  y = length(df$Task) + 1,
  label = format(important_dates, "%Y-%m-%d"),
  position = label_positions
)

Create and output plots (charts)

Generate a plot using ggplot2.

p <- ggplot() +
  geom_segment(data = df, aes(x = Start, xend = End, y = Task, yend = Task, color = Section), size = 8) +
  geom_vline(xintercept = important_dates, linetype = "dashed", color = "darkgray") +
  geom_text(data = date_labels,
            aes(x = x, y = y + ifelse(position == 0, -0.5, 0.5), label = label),
            angle = 90, hjust = ifelse(date_labels$position == 0, 1, 0), vjust = 0.5, size = 3) +
  scale_x_date(date_labels = "%Yyear %mmonth", date_breaks = "3 months") +
  scale_y_discrete(limits = c(df$Task, "", "")) +
  theme_minimal() +
  labs(title = "Lease renewal and termination schedule (example)",
       x = "date", y = "") +
  theme(legend.position = "bottom",
        plot.title = element_text(hjust = 0.5, size = 16),
        axis.text.x = element_text(angle = 45, hjust = 1),
        panel.grid.minor = element_blank())

print(p)

Save as PNG format

Save the resulting plot as a PNG file.

ggsave("lease_renewal_process_with_alternating_labels.png", plot = p, width = 15, height = 10, dpi = 300)

Full source code

Below is the full source code described above. Paste it in and run it to see the image you saw at the top of the post.

# 필요한 패키지 설치 및 로드
if (!require(ggplot2)) install.packages("ggplot2")  # ggplot2 패키지가 없으면 설치
if (!require(dplyr)) install.packages("dplyr")      # dplyr 패키지가 없으면 설치
library(ggplot2)  # ggplot2 패키지 로드 (그래프 생성용)
library(dplyr)    # dplyr 패키지 로드 (데이터 조작용)

# 데이터 프레임 생성
df <- data.frame(
    Task = c("초기 계약 기간", "집주인 통지 가능 기간", "세입자 통지 가능 기간","갱신 계약 기간", "통보 후 3개월"),  # 각 기간의 이름
    Start = as.Date(c("2021-02-03", "2022-08-03", "2022-08-03","2023-02-03", "2023-05-01")),  # 각 기간의 시작일
    End = as.Date(c("2023-02-02", "2022-12-02", "2022-12-02","2025-02-02", "2023-07-30")),    # 각 기간의 종료일
    Section = c("초기 계약", "갱신 거절 통지", "갱신 거절 통지","갱신 계약", "계약 해지")  # 각 기간의 분류
)

# 중요한 날짜 데이터 프레임 생성
important_dates <- as.Date(c("2021-02-03", "2023-02-02", "2022-08-03", "2022-12-02",
                             "2023-01-02", "2023-02-03", "2025-02-02",
                             "2023-05-01", "2023-08-01"))  # 중요한 날짜들을 벡터로 정의
important_dates <- sort(important_dates)  # 날짜를 오름차순으로 정렬

# 날짜 레이블 위치 조정 함수 개선
adjust_label_position <- function(dates) {
    n <- length(dates)
    positions <- rep(0, n)  # 모든 위치를 0으로 초기화
    last_position <- 0
    for (i in 2:n) {
        if (as.numeric(dates[i] - dates[i-1]) <= 7) {  # 7일 이내의 근접한 날짜 확인
            positions[i] <- (last_position + 1) %% 2     # 이전 위치에 따라 상하 교대 (0 또는 1)
            last_position <- positions[i]
        } else {
            last_position <- 0
        }
    }
    return(positions)
}

# 날짜 레이블 위치 조정
label_positions <- adjust_label_position(important_dates)

# 날짜 레이블 데이터 프레임 생성
date_labels <- data.frame(
    x = important_dates,  # x축 위치 (날짜)
    y = length(df$Task) + 1,  # y축 위치 (모든 Task 위에 위치)
    label = format(important_dates, "%Y-%m-%d"),  # 레이블 텍스트 (날짜 형식)
    position = label_positions  # 레이블의 상하 위치 (0 또는 1)
)

# 플롯 생성
p <- ggplot() +
    geom_segment(data = df, aes(x = Start, xend = End, y = Task, yend = Task, color = Section), size = 8) +
    # 각 Task에 대한 기간을 나타내는 선분. x: 시작일, xend: 종료일, y: Task 이름, color: Section으로 색상 구분
    
    geom_vline(xintercept = important_dates, linetype = "dashed", color = "darkgray") +
    # 중요한 날짜에 수직선 추가. linetype: 점선, color: 진한 회색
    
    geom_text(data = date_labels,
              aes(x = x, y = y + ifelse(position == 0, -0.5, 0.5), label = label),
              angle = 90, hjust = ifelse(date_labels$position == 0, 1, 0), vjust = 0.5, size = 3) +
    # 날짜 레이블 추가. x: 날짜 위치, y: Task 위 또는 아래, label: 날짜 텍스트
    # angle: 90도 회전, hjust & vjust: 레이블 정렬, size: 글자 크기
    
    scale_x_date(date_labels = "%Y년 %m월", date_breaks = "3 months") +
    # x축 날짜 형식 설정. date_labels: 년월 표시 형식, date_breaks: 3개월 간격으로 눈금 표시
    
    scale_y_discrete(limits = c(df$Task, "", "")) +
    # y축 설정. limits: Task 이름들과 추가 여백 설정
    
    theme_minimal() +  # 최소한의 테마 적용
    labs(title = "임대차 계약 갱신 및 해지 스케쥴 (예시)",
         x = "날짜", y = "") +  # 그래프 제목, x축 레이블 설정
    theme(legend.position = "bottom",  # 범례 위치를 아래로 설정
          plot.title = element_text(hjust = 0.5, size = 16),  # 제목 중앙 정렬 및 크기 설정
          axis.text.x = element_text(angle = 45, hjust = 1),  # x축 레이블 45도 회전
          panel.grid.minor = element_blank())  # 작은 격자선 제거

# 플롯 출력
print(p)

# PNG 형식으로 저장
ggsave("lease_renewal_process_with_alternating_labels.png", plot = p, width = 15, height = 10, dpi = 300)
# 파일명, 플롯 객체, 너비, 높이, 해상도 설정

Organize

In this post, we learned how to use R to visualize a lease renewal and termination schedule. Representing a complex contract schedule as a visualized schedule table makes it easy to see important dates at a glance.

First, I installed the necessary packages, prepared the data, and wrote a function to adjust the date labels so that they don't overlap. Then, I explained the process of using ggplot2 to create a visualization of the lease term and important dates, and saving it as a PNG file.

This visualization technique can help you not only with lease agreements, but also with a variety of scheduling and project planning. As you continue to explore different data visualization techniques, practice communicating the meaning of your data clearly. Additionally, we hope that you will develop the ability to make better decisions through visualized data.

Similar Posts