Как преобразовать таблицу смертности для создания графика Каплана-Мейера

#r #dplyr #datatable #survival-analysis #survival

Вопрос:

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

Данные, которые я обычно имею, имеют следующий формат:

 ID Entry_type Departure_type Birth_date Death_date  Lifespan
234 B 1 2008-05-01 2020-01-20 10.986995
549 B 1 2014-05-25 2016-02-09 1.711157
235 B 1 2015-02-01 2017-08-01 2.496920ID
 

Эти данные содержат по одному человеку в строке, указанной их идентификатором. Последняя колонка-это продолжительность жизни этого человека

Я могу сгенерировать график Каплана-Мейера из этой таблицы, используя код:

 survival_plot <- ggsurvplot(
    fit = survfit(Surv(Lifespan, Depart.Type) ~ 1, data = life_span_table), 
    xlab = "Years", 
    ylab = "Overall survival probability",
    surv.median.line = "hv",
    title = "Survival Curve",
    legend.title="")
 

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

 Year Age Total BirthYear CumDeath
1905  0 9262 1905 9262
1906 1 1335 1905 10597
1907 2 514 1905 11111
 

Пояснитель для столбцов:

 Year: The year being recorded.
Age: The age of the individual from the 1905 cohort in that year.
Total: The number of individuals born in 1905 who died in the recorded year.
BirthYear: Always 1905 for this cohort (redundant information)
CumDeath: The total number of people from the cohort who have died at the point of recording (cumulative death). 
 

Таким образом, в этом формате данных нет отдельного человека в строке, как это было ранее.
Я чувствую, что единственный способ создать идентичные графики Каплана-Мейера, используя эти данные, — это переформатировать их так, чтобы в каждой строке было по одному человеку, а данные об их продолжительности жизни добавлялись в виде нового столбца в соответствии с форматом, с которым я обычно работаю.

Продолжительность жизни можно рассчитать как разницу между годом и Годом рождения, но мне нужно было бы сделать количество строк для каждой продолжительности жизни равным общей записи за каждый год. Затем я могу добавить столбец Entry_Type и Departure_Type для каждой строки, который всегда будет » B «для Entry_type и» 1 » для Departure_type.

Обычно я использую dplyr для переформатирования таблиц, но я не уверен, что лучший способ добавления новых строк для каждого срока службы зависит от общей записи. Может ли dplyr сделать это, или мне лучше использовать функцию loop или lapply?

Мы будем очень признательны за любую помощь.

Комментарии:

1. Вам следует почитать о построении «таблиц жизни». Существует несколько пакетов R, которые сделают это за вас.

Ответ №1:

Это оказывается довольно простым упражнением с использованием индексации строк R data.frame. Рассмотрим этот пример с игрушкой (который очень похож на ваш):

 tt = data.frame(name=c('a', 'b', 'c'), 
                count=c(1, 2, 3))
# extract counts specifying how many times to replicate each row
counts = tt$count
# construct row indexes
row_positions = seq_along(counts)
# or
row_positions = seq(1, nrow(tt))
# inflate vector of row indexes according to the counts
row_pos_replicated = rep(row_positions, counts)
# use inflated indexes to expand frame rows per `count` values
tt_replicated = tt[row_pos_replicated,]
 

Мы просто расширили строки из tt нового фрейма tt_replicated в соответствии со count столбцом:

 > tt_replicated
       name  count
1      a     1
2      b     2
2.1    b     2
3      c     3
3.1    c     3
3.2    c     3
 

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

 census_data = read.csv(text = "Year Age Total BirthYear CumDeath
1905 0 9262 1905 9262
1906 1 1335 1905 10597
1907 2 514 1905 11111", sep="")

census_data_for_KMplot = census_data[rep(seq(1,
                                             nrow(census_data)),
                                         census_data$CumDeath),]
 

Давайте подсчитаем количество строк для каждой Year (с помощью data.table ):

 > data.table::setDT(census_data_for_KMplot)[, .N, by=Year]
   Year     N
1: 1905  9262
2: 1906 10597
3: 1907 11111
 

Использование data.table для ускорения и несколько более простого синтаксиса (обратите sep= fread , внимание, что при индексировании строк нет ни внутри, ни [] внутри):

 library(data.table)

census_data = fread(text = "Year Age Total BirthYear CumDeath
1905 0 9262 1905 9262
1906 1 1335 1905 10597
1907 2 514 1905 11111")

census_data_for_KMplot = census_data[rep(seq_along(census_data$CumDeath), 
                                     census_data$CumDeath)]
census_data_for_KMplot[, .N, by=Year]

   Year     N
1: 1905  9262
2: 1906 10597
3: 1907 11111
 

Комментарии:

1. Спасибо, я думаю, что это очень близко, но я неправильно выразился, я должен был сказать, что это зависит от полной смерти, а не от смерти. За 1907 год должно быть только 514 строк/записей, потому что 514 человек, родившихся в 1905 году, умерли в этом году. В вашем коде N увеличивается с каждым годом, но мне нужно количество строк за каждый год, соответствующее значению в столбце «Всего». Я постараюсь изменить код, так как это была моя ошибка.