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 ниже порогового значения, примет первое значение (срез) и вернет его.