#r #mapply
Вопрос:
Мне нужно отсканировать почти миллион точек данных и определить, находятся ли они ниже или выше порогового значения. У меня есть порог, определенный глобально, и у меня есть простая предопределенная функция
function.lower.penalty lt;- function(i,j){ if( i lt; j ){ #if gate condition is met, flip the gate flag: n lt;- 1 }else{nlt;-0} return(n) }
это я вызываю с помощью mapply, который запишет столбец с флагом 0/1 в мой фрейм данных:
df[, paste0("outside.highpass")] lt;- mapply(function.lower.penalty,i="somesignal.found.in.df", j="*some.threshold.found.in.df*" )
Это довольно просто, я могу отмечать десятки сигналов с соответствующими пороговыми значениями, как это, во втором большом кадре данных. Кроме того, учитывая, как записывается пороговое значение, код либо помечает сигналы как ниже/выше порогового значения (это означает, что у меня также есть функция.выше.штраф).
Теперь меня попросили сделать более сложный порог, имеющий форму многосегментированной линии. Каков самый быстрый способ пометить точки данных, учитывая, что здесь видны только угловые точки многосегментированной линии (я могу угадать их по тому, как они нарисовали линию).
До сих пор у меня был заранее определенный порог (серый 0,2), и я использовал mapply для сканирования сигнала, нарисованного по оси x. Я просто использовал функцию для возврата 0 или 1, если точка данных была меньше или больше порогового значения. Теперь мне нужна многосегментная линия, подобная той, что нарисована красным, для выполнения той же работы.
Изменить: Используя предложение det, я смог пометить точки данных в кадре данных. Однако, похоже, что некоторые точки данных, близкие к определенной строке, неверно оценены, см. Здесь. Мне интересно, как это обойти, или это ошибка при рисовании?
Ответ №1:
Вы можете создать функцию, которая возвращает кусочно-линейную функцию на основе точек:
picewiseLinear lt;- function(x.var, y.var){ stopifnot(length(x.var) == length(y.var), sum(duplicated(x.var)) == 0) p lt;- order(x.var) x.var lt;- x.var[p] y.var lt;- y.var[p] k lt;- diff(y.var) / diff(x.var) l lt;- -1 * k * head(x.var, -1) head(y.var, -1) function(x){ ind lt;- findInterval(x, x.var) if(!all(between(ind, 1, length(x.var) - 1))) stop("wrong input") x * k[ind] l[ind] } }
Например:
point_df lt;- tribble( ~x, ~y, 3, 0, 5, 2, 3, 3, 5, 4 ) f lt;- picewiseLinear(point_df$y, point_df$x)
(на вашей картинке у вас есть кусочно-линейная функция, но вы рассматриваете x как зависимую переменную)
и на примере набора данных вы получаете что-то вроде этого:
set.seed(123) tibble( x = runif(1000, 0, 6), y = runif(1000, 0, 4) ) %gt;% mutate(color = ifelse(x gt; f(y), "red", "blue")) %gt;% ggplot(aes(x, y)) geom_point(aes(color = color)) scale_color_identity() geom_path(data = point_df)
Комментарии:
1. Большое вам спасибо за этот ответ! Мне удалось адаптировать его, и вместо раскраски я создаю столбец с соответствующим номером подмножества. Однако, если я построю график, то два подмножества, я понял, что некоторые точки, близкие к многосегментированной линии, по-видимому, помечены неправильно. Смотрите картинку, которую я добавил в своем РЕДАКТИРОВАНИИ. Однако я не уверен, что это ошибка при рисовании.
2. возможно, это связано с тем фактом, что у вас есть логарифмическая шкала на графиках. Попробуйте использовать обычный масштаб (подмножество данных по этим регионам, если это необходимо для лучшего контроля).