Почему мой цикл for с оператором if не работает?

#r #for-loop #if-statement

Вопрос:

Извините, если у этого есть очевидное решение, но я не очень хорошо знаком с условными утверждениями, я некоторое время сталкивался с этой проблемой и не смог найти ошибку.

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

 > samples[,c(2,360,361)]
     patient_id  sample_id timepoint
d1.18    1056023 1056023.d1        d1
d1.4     3278638 3278638.d1        d1
d1.37     858412  858412.d1        d1
d4.4     3278638 3278638.d4        d4
d4.31     467506  467506.d4        d4
d4.29    1064441 1064441.d4        d4
d1.29    1064441 1064441.d1        d1
d4.37     858412  858412.d4        d4
d4.22     967710  967710.d4        d4
d1.52     294224  294224.d1        d1
d4.51     907354  907354.d4        d4

 

Для некоторых пациентов у меня есть два образца в двух разных временных точках: d1 и d4. Для других у меня есть только d1 или d4. Я хотел бы выбрать только один образец для каждого пациента, выбрав d1, если доступны два образца. Мой конечный фрейм данных должен выглядеть следующим образом:

 > samples[,c(2,360,361)]
      patient_id  sample_id timepoint
d1.18    1056023 1056023.d1        d1
d1.4     3278638 3278638.d1        d1
d1.37     858412  858412.d1        d1
d4.31     467506  467506.d4        d4
d1.29    1064441 1064441.d1        d1
d4.22     967710  967710.d4        d4
d1.52     294224  294224.d1        d1
d4.51     907354  907354.d4        d4

 

Таков был мой подход:

 for(i in unique(samples$patient_id)){
  if((sum(samples$patient_id == i)) == 2){
    samples <- samples[-(samples$patient_id == i amp; samples$timepoint == d4),]
  }
}
 

Хотя мой конечный кадр данных имеет такое же количество строк, как и длина, у unique(samples$patient_id) некоторых пациентов они полностью исчезли, а у других все еще есть оба образца.

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

 patients <- unique(samples$patient_id)
dat <- list()

for(i in patients){
  
  if((sum(samples$patient_id == i)) == 2){
    dat[[i]] <- paste(i, "d1", sep = ".")
  }else if ((sum(samples$patient_id == i)) == 1){
    dat[[i]] <- paste(i, "d4", sep = ".")
  } else{
    NULL
  }
}
 

Но в результате получается список из 1314182 элементов.

Я был бы очень признателен за любую помощь!

Ответ №1:

Более простым решением было бы следующее:

 library(dplyr)  
                        
samples %>%
  arrange(patient_id, timepoint) %>%
  distinct(patient_id, .keep_all = TRUE)
 

Что приводит к:

      id patient_id  sample_id timepoint
1 d1.52     294224  294224.d1        d1
2 d4.31     467506  467506.d4        d4
3 d1.37     858412  858412.d1        d1
4 d4.51     907354  907354.d4        d4
5 d4.22     967710  967710.d4        d4
6 d1.18    1056023 1056023.d1        d1
7 d1.29    1064441 1064441.d1        d1
8  d1.4    3278638 3278638.d1        d1