R найти первое значение в кадре данных, который попадает в заданный порог

Я довольно новый пользователь, и мне нужна ваша помощь с задачей, на которой я застрял. Если бы мой вопрос был задан / дан ответ раньше, я был бы признателен, если бы вы могли направить меня на соответствующую страницу.

У меня есть следующий набор данных (lbnp_br), который представляет собой оптическую плотность (OD), измеренную во времени (в секундах):

 time   OD
1891    -244.6
1891.5  -244.4
1892    -242
1892.5  -242
1893    -241.1
1893.5  -242.4
1894    -245.2
1894.5  -249.6
**1895  -253.9**
1895.5  -254.5
1896    -251.9
1896.5  -246.7
1897    -242.4
1897.5  -234.6
1898    -225.5

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

Для этого я рассчитал коэффициент вариации (CV) OD и использую среднее значение OD (-252,9098) +/- 2*CV для определения порога ответа. Для вышеуказанных данных пороговое значение устанавливается как (среднее значение OD + 2*CV = -252,9917) и (среднее значение OD - 2*CV = -252,8278).

Теперь мне нужно рассчитать время в секундах от начала (1891 секунда) до первого значения OD, которое превышает +/- пороговые значения. Например, для вышеупомянутого кадра данных этот порог превышен на 1895 секунд, что соответствует OD -253,9.

Теперь я должен повторить это 3 раза для каждого предмета исследования и для 17 предметов в целом, поэтому я ищу функцию, в которой я могу определить фрейм данных и пороговые значения, и он вернет первое значение ОП, если оно превышает определенный пороги (all_threshold $ sup_2_minus) и (all_threshold $ sup_2_plus) и соответствующее ему время.

я пытался subset рекомендуется в другом месте:

subset(lbnp_br, lbnp_br$OD < all_threshold$sup_2_minus & lbnp_br$OD > all_threshold$sup_2_plus)  

Тем не менее, это не возвращает то, что я ищу.

а также

ifelse(lbnp_br$OD > all_threshold$sup_2_plus & lbnp_br$OD < all_threshold$sup_2_minus, lbnp_br$OD, NA)

который возвращает NA и не указывает точное значение OD и время.

3 ответа

Один лайнер:

function (dfr, threshold) dfr$OD[ min(which(dfr$OD > threshold)) ]

Выдает предупреждение и NA если во фрейме данных нет такой строки, что, вероятно, то, что вы хотите.

Альтернатива, purrrрешение на основе:

function (dfr, threshold) purrr::detect(dfr$OD, ~ .x > threshold)

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

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

find_time <- function(df, df2, df3, threshold_1, threshold_2, threshold_3, threshold_4, threshold_5, threshold_6){
  return_value_1 = df %>%
    arrange(time) %>%
    filter(OD > threshold_1) %>%
    slice_(1)
  colnames(return_value_1)[1] <- "time_hdt_upper"
  colnames(return_value_1)[2] <- "OD_hdt_upper"

  if (nrow(return_value_1) == 0) {
    return_value_1[1,1] <- NA
    return_value_1[1,2] <- NA
  }


  return_value_2 = df %>%
    arrange(time) %>%
    filter(OD < threshold_2) %>%
    slice_(1)
  colnames(return_value_2)[1] <- "time_hdt_lower"
  colnames(return_value_2)[2] <- "OD_hdt_lower"

  if (nrow(return_value_2) == 0) {
    return_value_2[1,1] <- NA
    return_value_2[1,2] <- NA
  }

  return_value_3 = df2 %>%
    arrange(time) %>%
    filter(OD > threshold_3) %>%
    slice_(1)
  colnames(return_value_3)[1] <- "time_lbnp_upper"
  colnames(return_value_3)[2] <- "OD_lbnp_upper"

  if (nrow(return_value_3) == 0) {
    return_value_3[1,1] <- NA
    return_value_3[1,2] <- NA
  }


  return_value_4 = df2 %>%
    arrange(time) %>%
    filter(OD < threshold_4) %>%
    slice_(1)
  colnames(return_value_4)[1] <- "time_lbnp_lower"
  colnames(return_value_4)[2] <- "OD_lbnp_lower"

  if (nrow(return_value_4) == 0) {
    return_value_4[1,1] <- NA
    return_value_4[1,2] <- NA
  }



  return_value_5 = df3 %>%
    arrange(time) %>%
    filter(OD > threshold_5) %>%
    slice_(1)
  colnames(return_value_5)[1] <- "time_hut_upper"
  colnames(return_value_5)[2] <- "OD_hut_upper"

  if (nrow(return_value_5) == 0) {
    return_value_5[1,1] <- NA
    return_value_5[1,2] <- NA
  }



  return_value_6 = df3 %>%
    arrange(time) %>%
    filter(OD < threshold_6) %>%
    slice_(1)
  colnames(return_value_6)[1] <- "time_hut_lower"
  colnames(return_value_6)[2] <- "OD_hut_lower"

  if (nrow(return_value_6) == 0) {
    return_value_6[1,1] <- NA
    return_value_6[1,2] <- NA
  }



  return(data.frame(return_value_1, return_value_2, return_value_3, return_value_4, return_value_5, return_value_6))


}

который дает

find_time_threshold <- find_time(hdt_br, lbnp_br, hut_br, all_threshold$base_plus, all_threshold$base_minus, all_threshold$sup_2_plus, all_threshold$sup_2_minus, all_threshold$sup_3_plus, all_threshold$sup_3_minus)
> find_time_threshold

  time_hdt_upper OD_hdt_upper time_hdt_lower OD_hdt_lower time_lbnp_upper OD_lbnp_upper time_lbnp_lower
1          596.5        123.3            506         91.3              NA            NA            1706
  OD_lbnp_lower time_hut_upper OD_hut_upper time_hut_lower OD_hut_lower
1        -27.89         3186.5       -82.98           2909       -211.7

Это не короткий ответ, но, надеюсь, ясно. Он использует пакет dplyr:

library(dplyr)

find_time = function(df, threshold){
  return_value = df %>%
    arrange(time) %>%
    filter(OD < threshold) %>%
    slice(1)
  return(return_value)
}

find_time(data, threshold)

Это отсортирует (упорядочит) ваши данные по времени, поднастроит (отфильтрует) ваши данные для значений OD ниже порогового значения, примет первое значение (срез) и вернет его.

Другие вопросы по тегам