> subset_data$image
  [1] "images/470_blur_80.jpg"     "images/440_contrast_70.jpg" "images/382_contrast_90.jpg" "images/9_jpeg_80.jpg"       "images/288_jpeg_80.jpg"     "images/115_contrast_70.jpg" 
"images/536_jpeg_70.jpg"     "images/39_original.jpg"     "images/65_jpeg_80.jpg"      "images/396_jpeg_70.jpg"    
"images/475_jpeg_80.jpg"     "images/345_blur_70.jpg"     "images/51_blur_80.jpg"      "images/226_blur_70.jpg"     "images/233_jpeg_90.jpg"     "images/177_blur_70.jpg"     "images/10_jpeg_80.jpg"      "images/149_blur_90.jpg"     "images/328_blur_70.jpg"     "images/190_contrast_90.jpg"

I have shown images either in their original state or with "jpeg", "blur" or "contrast"  distortion. If the images are distorted the can be distorted at levels "70", "80 or "90" which represents how many percentage of the original quality they are expected to have (SSIM). How can I elegantly separate the image into its different category names using the image name? Also propose BRMS models to predict another variable called ratings from the nested combination of image distortions and levels. Here is a first attempt:

# Find distortions and categories
# Image number 
subset_data$ImageNumber <- gsub("^\\D*([0-9]+)_.*$", "\\1", subset_data$image)

# Extract letters following the first underscore until a second underscore or ".jpg" is encountered
subset_data$distortion <- gsub("^[^_]+_(.*?)(_[^_]+\\.jpg|\\.jpg)$", "\\1", subset_data$image)

# Convert "original" to "none" 
subset_data$distortion[subset_data$distortion == "original"] <- "none"

# Extract last set of digits immediately followed by ".jpg" for each filename
subset_data$level <- gsub(".*_([0-9]+)\\.jpg$", "\\1", subset_data$image)

# Convert cases that are not "70", "80", or "90" to "100" 
subset_data$level[!subset_data$level %in% c("70", "80", "90")] <- "100"

# Factor variables
subset_data$distortion <- factor(subset_data$distortion, levels = c("none", "jpeg", "blur", "contrast"))
subset_data$level <- factor(subset_data$level, levels = c("100", "90", "80", "70"))

# BRMS model 
model <- brm(ratings ~ distortion*level, data = subset_data, iter = 2000, 
             family = gaussian, chains = 4)

One issue with this attempt is that it assumes that all distortion * level options are possible, but none will always have a quality of 100