Introduction

This tutorial walks you through the complete process of creating a Likert chart in R using real survey data stored in Excel format. We will:

This is ideal for visualizing survey responses based on agreement scales (e.g., Strongly disagree → Strongly agree).


Step 1: Load Required Packages

We use the pacman package to load and install the required libraries. If you don’t have pacman installed yet. Then, load the following libraries:

Step 2: Import Data from Excel

We read in an Excel file that contains the survey responses. Make sure your file is saved locally and named correctly.

p <- read_xlsx("vẽ likert Block B12-B29.xlsx", sheet = "Form Responses 1")
## New names:
## • `A02. Chuyên ngành` -> `A02. Chuyên ngành...3`
## • `A02. Chuyên ngành` -> `A02. Chuyên ngành...46`
## • `Factor 1` -> `Factor 1...72`
## • `Factor 2` -> `Factor 2...73`
## • `Factor 1` -> `Factor 1...75`
## • `Factor 2` -> `Factor 2...76`

Step 3: Select Likert-scale Variables

These are the variables corresponding to Likert-scale questions in your survey.

likert_vars <- c("B16", "B25", "B27", "B28", "B29", "B23", "B22", "B24",
                 "B14", "B17", "B26", "B21", "B15", "B12", "B20", "B19",
                 "B18", "B13")

Step 4: Convert Numeric Responses to Labeled Factors

Survey responses are typically recorded as numbers (e.g., 1 to 5). Here, we map them to meaningful labels (in Vietnamese in this case):

likert_labels <- c(
  "1" = "Rất không đồng ý",  # Strongly disagree
  "2" = "Không đồng ý",      # Disagree
  "3" = "Trung lập",         # Neutral
  "4" = "Đồng ý",            # Agree
  "5" = "Rất đồng ý"         # Strongly agree
)
likert_levels <- unname(likert_labels)

p_likert <- p[likert_vars] %>%
  lapply(function(x) {
    factor(
      likert_labels[as.character(x)],
      levels = likert_levels,
      ordered = TRUE
    )
  }) %>%
  as.data.frame()

Step 5: Assign Descriptive Labels to Each Question

This helps make the chart readable by replacing technical codes (e.g., B16) with full descriptions.

label_mapping <- c(
  B16 = "Áp lực công việc",             # Work pressure
  B25 = "Thiếu hỗ trợ địa phương",      # Lack of local support
  B27 = "Không được coi trọng",         # Not being valued
  B28 = "Bị phân tuyến do trình độ",     # Segregated by qualification
  B29 = "Bị phân tuyến do nghĩa vụ",     # Segregated by assignment
  B23 = "Thiếu thốn sinh hoạt",         # Poor living conditions
  B22 = "Nguy cơ mất an toàn",          # Safety risk
  B24 = "Không có phúc lợi cao",        # No good benefits
  B14 = "Khó đi lại",                    # Difficulty commuting
  B17 = "Việc không phù hợp kỹ năng",   # Mismatch with skills
  B26 = "Thiếu triển vọng cho gia đình",# No family future
  B21 = "Thiếu cơ hội thăng tiến",      # No promotion opportunities
  B15 = "Thiếu hỗ trợ cấp trên",        # No supervisor support
  B12 = "Điều kiện kém",                # Poor conditions
  B20 = "Thiếu triển vọng nghề",        # No career prospects
  B19 = "Ít cơ hội học tiếp",           # Few learning opportunities
  B18 = "Ít cơ hội phát triển nghề",    # Few professional growth opportunities
  B13 = "Thiếu vật chất"                # Lack of resources
)

colnames(p_likert) <- label_mapping[colnames(p_likert)]

Step 6: Create a Likert Object

We now convert the cleaned data frame into a Likert object that can be visualized.

likert_obj <- likert::likert(p_likert)

Step 7: Plot the Likert Chart

This will generate a horizontal stacked bar chart with neutral responses centered.

plot(
  likert_obj,
  wrap = 40,
  center = 3,
  include.center = TRUE,
  plot.percent.low = TRUE,
  plot.percent.high = TRUE,
  main = "Medical students' perceptions of grassroots healthcare"
) -> plot
ggsave(plot = plot,
       filename = here::here("plot.png"),
       width = 10, height = 6, dpi = 1500)
knitr::include_graphics(here("plot.png"))