Выполнение функции на каждом уровне нескольких столбцов в R

#r #survival-analysis

#r #анализ выживаемости

Вопрос:

Мне нужно выполнить функцию на каждом уровне нескольких столбцов в data.table . Например, используя lung набор данных из survival :

 library(survival)
library(data.table)
library(dplyr)

data(lung)
setDT(lung)

vars <- c("sex", "ph.ecog")
lung[, (vars) := lapply(.SD, factor), .SDcols = vars]

fit <- tibble()
for (i in levels(lung[, vars ])){
temp <-
coxph(
  Surv(time, status) ~ i,
  data = lung
) %>% 
broom::tidy(exp=T)
fit <- bind_rows(fit, temp)
  }
  

Это не работает — как я могу добиться успеха?

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

1. попробуйте удалить %>% в 4-й строке с конца. это так не работает. сохраните coxph в новой переменной и затем работайте с ней. %>% невозможно использовать оператор присваивания, как вы это сделали.

2. вы правы, я отредактировал это. но это не решает мою проблему.

Ответ №1:

Вы хотите запускать функцию для каждого уровня vars столбца или для каждого vars столбца?

Для последующего вы можете сделать :

 do.call(rbind,lapply(vars, function(x) {
  broom::tidy(coxph(reformulate(x, 'Surv(time, status)'), data = lung))
}))

#  term     estimate std.error statistic   p.value conf.low conf.high
#  <chr>       <dbl>     <dbl>     <dbl>     <dbl>    <dbl>     <dbl>
#1 sex2       -0.531     0.167     -3.18 0.00149    -0.859     -0.203
#2 ph.ecog1    0.369     0.199      1.86 0.0634     -0.0205     0.758
#3 ph.ecog2    0.916     0.225      4.08 0.0000448   0.476      1.36 
#4 ph.ecog3    2.21      1.03       2.15 0.0314      0.197      4.22 
  

Чтобы немного упростить, поскольку вы уже используете data.table , вы можете использовать rbindlist вместо do.call rbind .

Чтобы выполнить это для уровней в ваших данных, вы можете сделать :

 do.call(rbind, lapply(vars, function(x) do.call(rbind,
        lapply(levels(lung[[x]]), function(y) 
    broom::tidy(coxph(reformulate(x, 'Surv(time, status)'), 
            data = lung[lung[[x]] == y]))))))
  

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

1. Спасибо. Это решает указанную проблему. Тем не менее, я думаю, что я был достаточно ясен. Если бы в другом сценарии я хотел выполнить функцию на каждом уровне нескольких столбцов, как я мог бы это выполнить? В случае cox reg это, конечно, избыточно.

2. Как вы будете запускать ее для одной итерации без какого-либо цикла?

3. например. survfit(Surv (время, статус) ~ ph.ecog, данные = легкие [пол ==1] ). Тогда меня интересовал бы каждый уровень «пола» и несколько других столбцов.

4. Смотрите обновленный ответ, если это поможет. Убедитесь, что в ваших данных присутствуют все уровни факторов.

5. Я вижу, что это работает с использованием функции coxph, но не с функцией survfit, которая мне нужна:do.call(rbind, lapply(vars, функция(x) do.call(rbind, lapply(levels(lung[[x]]), функция(y) broom::tidy(survfit(переформулировать(x, ‘Surv (время, статус) ~ ph.ecog’), data = lung[легкое[[x]] == y] ))))))