Как создать в ggplot отдельные графики для каждого участника исследования

Вопрос или проблема

У меня есть данные из кросс-стадии, для которых мне нужно построить несколько графиков. Нет проблем с тем, чтобы нарисовать ‘средний’ график для всех испытуемых, но мне также нужны отдельные графики для каждого испытуемого с наложенными двумя лечениями (Т против R). И еще один вопрос – как назначить идентификатор испытуемого для каждого графика. Ниже приведены данные для 4 испытуемых (может быть больше, до 100).

structure(list(subj = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4), seq = c(2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), prd = c(1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2),
time = c(0, 0.333, 0.667, 1, 1.333, 1.667, 2, 2.5, 3, 3.5,
4, 6, 8, 12, 24, 48, 0, 0.333, 0.667, 1, 1.333, 1.667, 2,
2.5, 3, 3.5, 4, 6, 8, 12, 24, 48, 0, 0.333, 0.667, 1, 1.333,
1.667, 2, 2.5, 3, 3.5, 4, 6, 8, 12, 24, 48, 0, 0.333, 0.667,
1, 1.333, 1.667, 2, 2.5, 3, 3.5, 4, 6, 8, 12, 24, 48, 0,
0.333, 0.667, 1, 1.333, 1.667, 2, 2.5, 3, 3.5, 4, 6, 8, 12,
24, 48, 0, 0.333, 0.667, 1, 1.333, 1.667, 2, 2.5, 3, 3.5,
4, 6, 8, 12, 24, 48), conc = c(0,
0, 103.041, 301.731, 371.722, 341.099, 326.791, 279.52, 262.657,
234.926, 220.389, 141.804, 112.702, 68.981, 31.9, NA, 0,
0, 0, 0, 11, 24.436, 57.257, 122.065, 159.702, 271.629, 402.88,
154.535, 126.576, 75.999, 33.272, NA, 0, 0, 0, 0, 0, 25.932,
134.108, 257.836, 250.676, 237.466, 248.142, 142.511, 116.839,
66.76, 23.942, NA, 0, 0, 0, 27.992, 78.208, 306.763, 361.578,
303.356, 248.948, 193.574, 184.743, 104.518, 76.36, 44.371,
15.609, NA, 0, 49.073, 356.27, 546.462, 764.171, 822.19,
910.403, 818.073, 687.538, 601.246, 598.949, 301.036, 265.579,
129.278, 55.892, 11.525, 0, 60.115, 316.231, 496.366, 764.952,
1086.271, 982.368, 839.902, 757.569, 622.151, 733.912, 314.365,
242.839, 138.138, 67.617, 15.515, 0, 0, 51.362, 135.969,
253.814, 353.437, 346.998, 314.292, 385.864, 516.589, 627.003,
263.782, 274.407, 127.667, 45.013, NA, 0, 0, 0, 59.682, 237.216,
380.224, 528.946, 523.512, 446.714, 417.835, 352.487, 199.18,
195.568, 99.99, 39.81, NA), drug = c(“T”, “T”, “T”, “T”,
“T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”,
“R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”,
“R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”,
“R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “T”, “T”, “T”, “T”,
“T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”,
“R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”,
“R”, “R”, “R”, “R”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”,
“T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”,
“T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”, “T”,
“R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”, “R”,
“R”, “R”, “R”, “R”)), row.names = c(NA, -128L), class = c(“tbl_df”,
“tbl”, “data.frame”))

Код, который я использую для ‘среднего’ графика, следующий:

data <-
  Totalplot |>   
  group_by(drug, time) |>
  summarise(conc = mean(conc, na.rm = TRUE))   
plot <-
  ggplot(
    data = data, aes(x = time, y = conc, color = drug)) +
  geom_point(
    aes(
      group = interaction(drug, time)), alpha = 0.5, shape = 2, position = position_jitter(width = 0.1, height = 0)) +
  geom_line(data = data, linewidth = 0.5) +
  xlab('Time, h') + 
  ylab('Drug X plasma conc. ng/ml') +
  labs(title="Mean plasma concentration") +
  theme_bw()      

Используйте lapply:

subjectsIDs <- unique(Totalplot$subj)
plots <- lapply(subjectIDs, function(x) {
  Totalplot %>% filter(subj == x) %>%
    ggplot(
      aes(x = time, y = conc, color = drug)) +
    geom_point(
      aes(
        group = interaction(drug, time)), alpha = 0.5, shape = 2, position = position_jitter(width = 0.1, height = 0)) +
    geom_line(linewidth = 0.5) +
    xlab('Time, h') + 
    ylab('Drug X plasma conc. ng/ml') +
    labs(title = paste('Subject', x, 'plasma concentration')) +
    theme_bw()
})

Не уверен, что это то, что вы имеете в виду под назначением идентификатора испытуемого для каждого графика, но вы можете назвать каждый элемент списка графиков:

names(plots) <- subjectIDs

Это позволит вам получить доступ к каждому графику так:

plots[["1"]]

вставьте описание изображения здесь

Если вы не хотите, чтобы графики для испытуемых без данных на 48 часах имели дополнительное пространство справа, отфильтруйте NA:

subjectsIDs <- unique(Totalplot$subj)
plots <- lapply(subjectsIDs, function(x) {
  Totalplot %>% filter(subj == x, !is.na(conc)) %>%
    ggplot(
      aes(x = time, y = conc, color = drug)) +
    geom_point(
      aes(
        group = interaction(drug, time)), alpha = 0.5, shape = 2, position = position_jitter(width = 0.1, height = 0)) +
    geom_line(linewidth = 0.5) +
    xlab('Time, h') + 
    ylab('Drug X plasma conc. ng/ml') +
    labs(title = paste('Subject', x, 'plasma concentration')) +
    theme_bw()
})
names(plots) <- subjectsIDs
plots[["1"]]

вставьте описание изображения здесь


В качестве альтернативы, если вы хотите все графики расположить в сетке:

plot <- Totalplot %>%
  ggplot(
    aes(x = time, y = conc, color = drug)) +
  geom_point(
    aes(
      group = interaction(drug, time)), alpha = 0.5, shape = 2, position = position_jitter(width = 0.1, height = 0)) +
  geom_line(linewidth = 0.5) +
  xlab('Time, h') + 
  ylab('Drug X plasma conc. ng/ml') +
  labs(title="Plasma concentration by subject") +
  theme_bw() +
  facet_wrap(facets = vars(subj))
plot

вставьте описание изображения здесь

Ответ или решение

Для того чтобы создать отдельные графики для каждого участника в исследовании с использованием библиотеки ggplot2 в языке программирования R, вам потребуется следовать определенной последовательности шагов. Этот процесс включает агрегацию данных, использование функции lapply для создания списка графиков и, при необходимости, применение функции facet_wrap для отображения всех графиков в виде сетки. Давайте рассмотрим это более подробно.

1. Подготовка данных

Прежде всего, убедитесь, что ваши данные находятся в нужном формате. Ваши данные должны включать идентификатор участников (например, subj), время (time), концентрацию препарата (conc) и тип препарата (drug).

2. Агрегация данных для среднего графика

Вы уже реализовали агрегацию данных, чтобы построить график среднего значения для всех участников. Ваш код для усредненного графика выглядит следующим образом:

data <- Totalplot |>
  group_by(drug, time) |>
  summarise(conc = mean(conc, na.rm = TRUE))

plot <- ggplot(data, aes(x = time, y = conc, color = drug)) +
  geom_point(aes(group = interaction(drug, time)), alpha = 0.5, shape = 2, position = position_jitter(width = 0.1, height = 0)) +
  geom_line(data = data, linewidth = 0.5) +
  xlab('Time, h') +
  ylab('Drug X plasma conc. ng/ml') +
  labs(title="Mean plasma concentration") +
  theme_bw()

3. Создание отдельных графиков для каждого участника

Теперь для создания отдельных графиков для каждого участника можно использовать функцию lapply. Вот как это можно сделать:

library(ggplot2)
library(dplyr)

# Получаем уникальные идентификаторы участников
subjectsIDs <- unique(Totalplot$subj)

# Создаем список графиков для каждого участника
plots <- lapply(subjectsIDs, function(x) {
  Totalplot %>%
    filter(subj == x) %>%
    ggplot(aes(x = time, y = conc, color = drug)) +
    geom_point(aes(group = interaction(drug, time)), alpha = 0.5, shape = 2, position = position_jitter(width = 0.1, height = 0)) +
    geom_line(linewidth = 0.5) +
    xlab('Time, h') +
    ylab('Drug X plasma conc. ng/ml') +
    labs(title = paste('Subject', x, 'plasma concentration')) +
    theme_bw()
})

# Назначаем имена графикам
names(plots) <- subjectsIDs

Теперь у вас есть список графиков, где каждый график соответствует участнику. Для доступа к графику конкретного участника можно использовать следующий код:

plots[["1"]]  # Получение графика для участника 1

4. Альтернативный способ – использование facet_wrap

Если вы хотите сэкономить место и увидеть все графики на одном экране, вы можете использовать функцию facet_wrap. Это позволит вам автоматически разделить данные по участникам и построить графики в виде сетки:

plot <- Totalplot %>%
  ggplot(aes(x = time, y = conc, color = drug)) +
  geom_point(aes(group = interaction(drug, time)), alpha = 0.5, shape = 2, position = position_jitter(width = 0.1, height = 0)) +
  geom_line(linewidth = 0.5) +
  xlab('Time, h') +
  ylab('Drug X plasma conc. ng/ml') +
  labs(title="Plasma concentration by subject") +
  theme_bw() +
  facet_wrap(~ subj)

print(plot)

Этот подход позволит вам визуализировать данные по всем участникам сразу, что создаст более целостное представление о результатах исследования.

Заключение

С помощью методов, описанных выше, вы можете создавать отдельные графики для каждого участника или же комбинировать их в едином пространстве для более удобного анализа и визуализации. Это не только упростит ваш процесс анализа данных, но и сделает результаты более наглядными и доступными для интерпретации. Не забудьте проверить данные на пропуски и убедиться, что они корректны перед визуализацией.

Оцените материал
Добавить комментарий

Капча загружается...