You can use the pivot_longer() function from the tidyr package.
Starting from the data you provided, you can do something like below.
library(dplyr)
library(tidyr)
library(ggplot2)
raw_data <- data.frame(
X4.1_Online = c(7L, 5L, 7L, 7L, 4L, 1L, 2L, 1L, 6L),
X4.2_Mall = c(5L, 4L, 2L, 5L, 1L, 4L, 6L, 3L, 1L),
X4.3_Discounter = c(5L, 4L, 2L, 5L, 1L, 4L, 1L, 3L, 1L),
X4.4_market = c(6L, 5L, 4L, 5L, 4L, 4L, 7L, 2L, 4L),
X4.5_Outlet = c(6L, 1L, 2L, 6L, 6L, 1L, 7L, 2L, 4L),
X4.6_ = c(1L, 7L, 3L, 6L, 1L, 1L, 2L, 3L, 1L),
X4.7_ = c(1L, 1L, 3L, 5L, 1L, 1L, 4L, 4L, 3L),
X4.8_ = c(1L, 1L, 2L, 4L, 1L, 1L, 1L, 5L, 1L),
X4.9_ = c(1L, 1L, 1L, 1L, 1L, 5L, 1L, 7L, 1L),
X4.10_ = c(5L, 6L, 5L, 5L, 1L, 2L, 1L, 4L, 4L),
X4.11_ = c(4L, 2L, 5L, 4L, 2L, 1L, 1L, 7L, 1L),
X4.12_ = c(7L, 2L, 4L, 6L, 4L, 1L, 5L, 5L, 3L),
X4.13_ = c(7L, 7L, 5L, 7L, 1L, 4L, 4L, 7L, 5L),
D1_Age = c(26L, 40L, 25L, 56L, 28L, 72L, 60L, 60L, 23L)
) %>%
# add an ID column for clarity when looking at the long data - not technically needed
mutate(id = 1:n())
long_data <- raw_data %>%
# you can list all the relevant columns (the ones that have scores in them)
# in a vector of strings or do something like this. I'm grabbing all those
# with "X4" since that works for your sample data but you may need to change this.
pivot_longer(cols = names(.)[grepl("X4", names(.))],
names_to = "type",
values_to = "score") %>%
# group the ages
mutate(age_group = case_when(
D1_Age >= 70 ~ "70+",
D1_Age >= 60 ~ "60-69",
D1_Age >= 50 ~ "50-59",
D1_Age >= 40 ~ "40-49",
D1_Age >= 30 ~ "30-39",
D1_Age >= 20 ~ "20-29",
D1_Age >= 10 ~ "10-19",
TRUE ~ "--ERROR--"
))
ggplot(long_data,
aes(x = age_group,
y = score)) +
geom_boxplot() +
facet_wrap(.~type)