Найти DOY, соответствующий данному процентилю
У меня есть фрейм данных с ежедневными значениями NDVI с 2013 по 2017 год. Мой фрейм данных содержит непрерывные данные NDVI (т. Е. Для каждого дня года), но вот воспроизводимый пример структуры моего фрейма данных:
year <- sample(2013:2017, 750,replace=TRUE)
DOY <- sample(1:365, 750,replace=TRUE)
NDVI<- runif(750, -1, 1)
df <- cbind(year,DOY,NDVI)
Я использую функции quantile и tapply, чтобы найти для каждого года в кадре данных значение NDVI, соответствующее 10-му, 30-му, 50-му и 80-му процентилю:
quantile=do.call("rbind", tapply(df$NDVI, df$year, quantile,c(0.10, 0.30, 0.50, 0.80)))
Мой вопрос: как мне найти DOY, соответствующий 10-му, 30-му, 50-му, 80-му процентилю значений NDVI для каждого года? Например, если значение NDVI 0,3 соответствует 50-му процентилю 2014 года, я хотел бы вернуть DOY, соответствующий NDVI 0,3.
Спасибо за помощь!
2 ответа
Это решение, аналогичное решению Лена, и я повторяю то, что они говорят о трудностях точного совпадения. Я использовал то же самое семя, чтобы сделать результаты сопоставимыми. Разница в том, что я держу квантили в длинной форме, что облегчает этап фильтрации.
library("tidyverse")
set.seed(1)
year <- sample(2013:2017, 750,replace=TRUE)
DOY <- sample(1:365, 750,replace=TRUE)
NDVI<- runif(750, -1, 1)
df <- data_frame(year,DOY,NDVI)
df %>% group_by(year) %>%
do(data_frame(p = c(10, 30, 50, 80)/100, q = quantile(.$NDVI, probs = p))) %>%
full_join(df) %>%
group_by(year, p) %>%
slice(which.min(abs(NDVI - q)))
# A tibble: 20 x 5
# Groups: year, p [20]
year p q DOY NDVI
<int> <dbl> <dbl> <int> <dbl>
1 2013 0.100 -0.844 247 -0.844
2 2013 0.300 -0.459 96 -0.447
3 2013 0.500 -0.0144 202 -0.0144
4 2013 0.800 0.583 59 0.584
5 2014 0.100 -0.811 128 -0.818
6 2014 0.300 -0.403 37 -0.410
7 2014 0.500 -0.0136 187 -0.0136
8 2014 0.800 0.623 278 0.620
9 2015 0.100 -0.890 280 -0.887
10 2015 0.300 -0.494 330 -0.488
11 2015 0.500 -0.0332 316 -0.0332
12 2015 0.800 0.646 190 0.647
13 2016 0.100 -0.803 351 -0.803
14 2016 0.300 -0.447 206 -0.447
15 2016 0.500 -0.00170 122 -0.00170
16 2016 0.800 0.548 353 0.548
17 2017 0.100 -0.824 326 -0.830
18 2017 0.300 -0.484 124 -0.483
19 2017 0.500 -0.00704 175 -0.00900
20 2017 0.800 0.573 95 0.570
Проблема в том, что иногда процентиль не соответствует истинному наблюдению в NDVI. В этих случаях среднее значение принимает значения NDVI, например, около 30-го процентиля для года X. В этих случаях я взял два значения NDVI, которые являются ближайшими к значениям 30-го процентиля, вы можете выбрать оба или взять среднее значение соответствующих значений DOY. Возможно, это небольшой обходной путь, но это было лучшее, что я мог придумать сейчас:
set.seed(1)
year <- sample(2013:2017, 750,replace=TRUE)
DOY <- sample(1:365, 750,replace=TRUE)
NDVI<- runif(750, -1, 1)
df <- as.data.frame(cbind(year,DOY,NDVI))
library(dplyr)
library(tidyr)
library(broom)
df %>%
group_by(year) %>%
do( tidy(t(quantile(.$NDVI, c(0.10, 0.30, 0.50, 0.80)))) ) %>%
ungroup() %>%
right_join(df) %>%
arrange(year, NDVI) %>%
group_by(year) %>%
filter(abs(X10. - NDVI) == min(abs(X10. - NDVI)) |
abs(X30. - NDVI) == min(abs(X30. - NDVI)) |
abs(X50. - NDVI) == min(abs(X50. - NDVI))|
abs(X80. - NDVI) == min(abs(X80. - NDVI)))
Который дает:
year X10. X30. X50. X80. DOY NDVI
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 2013. -0.844 -0.459 -0.0144 0.583 247. -0.844
2 2013. -0.844 -0.459 -0.0144 0.583 96. -0.447
3 2013. -0.844 -0.459 -0.0144 0.583 202. -0.0144
4 2013. -0.844 -0.459 -0.0144 0.583 59. 0.584
5 2014. -0.811 -0.403 -0.0136 0.623 128. -0.818
6 2014. -0.811 -0.403 -0.0136 0.623 37. -0.410
7 2014. -0.811 -0.403 -0.0136 0.623 187. -0.0136
8 2014. -0.811 -0.403 -0.0136 0.623 278. 0.620
9 2015. -0.890 -0.494 -0.0332 0.646 280. -0.887
10 2015. -0.890 -0.494 -0.0332 0.646 330. -0.488