Рассчитать количество отрицательных значений между двумя датами - PullRequest
0 голосов
/ 22 апреля 2020

У меня есть фрейм данных значений SPEI. Я хочу рассчитать две статистики (объяснено ниже) с интервалом

  1. 20 лет, т.е. 2021-2040, 2041-2060, 2061-2080, 2081-2100. Первый столбец содержит дату (месяц-год) и
  2. каждый год, т. Е. 2021, 2022, 2023 и т. Д. c. до 2100 года.

Статистика:

  1. Частота засухи: Количество SPEI <0 за указанный период (соответственно 20 лет и 1 год) </li>
  2. Продолжительность засухи: равно количеству месяцев между началом (включенным) и месяцем окончания (не включенным) указанного периода. Я предполагаю, что событие засухи начинается, когда SPEI <0. </li>

Мне было интересно, есть ли способ сделать это в R? Это кажется легкой проблемой, но я не знаю, как это сделать. Пожалуйста, помогите мне. Excel занимает слишком много времени. Спасибо.

> head(test, 20)
         Date      spei-3
1  2021-01-01          NA
2  2021-02-01          NA
3  2021-03-01 -0.52133737
4  2021-04-01 -0.60047887
5  2021-05-01  0.56838399
6  2021-06-01  0.02285012
7  2021-07-01  0.26288462
8  2021-08-01 -0.14314685
9  2021-09-01 -0.73132256
10 2021-10-01 -1.23389220
11 2021-11-01 -1.15874943
12 2021-12-01  0.27954143
13 2022-01-01  1.14606657
14 2022-02-01  0.66872986
15 2022-03-01 -1.13758050
16 2022-04-01 -0.27861017
17 2022-05-01  0.99992395
18 2022-06-01  0.61024314
19 2022-07-01 -0.47450485
20 2022-08-01 -1.06682997

Редактировать: Мне очень нравится добавлять код, но я не знаю, с чего начать.

test = "E:/drought.xlsx"
#Extract year and month and add it as a column
test$Year =  format(test$Date,"%Y")
test$Month = format(test$Date,"%B")

Я не знаю, как go отсюда. Я обнаружил, что cumsum может помочь, но как выбрать один год, а затем применить cumsum к нему. Я не удерживаю код нарочно. Я просто не знаю с чего и как начать.

1 Ответ

0 голосов
/ 23 апреля 2020

Есть пара вопросов к сообщению ОП, поэтому я буду go читать их шаг за шагом. Для этого рабочего процесса вам понадобятся dplyr и lubridate.

Сначала мы создадим некоторые поддельные данные для использования:

library(lubridate)
library(dplyr)
#create example data
dd<- data.frame(Date = seq.Date(as.Date("2021-01-01"), as.Date("2100-12-01"), by = "month"),
                      spei = rnorm(960,0,2))

Это будет выглядеть примерно так, как вы иметь выше

> head(dd)
        Date        spei year   year_20 drought
1 2021-01-01 -6.85689789 2021 2021_2040       1
2 2021-02-01 -0.09292459 2021 2021_2040       1
3 2021-03-01  0.13715922 2021 2021_2040       0
4 2021-04-01  2.26805601 2021 2021_2040       0
5 2021-05-01 -0.47325008 2021 2021_2040       1
6 2021-06-01  0.37034138 2021 2021_2040       0

Затем мы можем использовать lubridate и cut для создания наших годовых и 20-летних переменных, чтобы сгруппировать их позже и создать столбец drought, обозначающий, если spei был отрицательным.

#create a column to group on by year and by 20-year
dd <- dd %>%
  mutate(year  = year(Date),
         year_20 = cut(year, breaks = c(2020,2040,2060,2080, 2100), include.lowest = T,
                       labels = c("2021_2040", "2041_2060", "2061_2080", "2081_2100")))  %>%
  #column signifying if that month was a drought
  mutate(drought = ifelse(spei<0,1,0))

Получив это, мы просто используем функцию group_by, чтобы получить частоту (или количество месяцев с засухой) по году или 20-летнему периоду

#by year
dd %>%
  group_by(year) %>%
  summarise(year_freq = sum(drought)) %>%
  ungroup()

# A tibble: 80 x 2
    year year_freq
   <dbl>     <dbl>
 1  2021         6
 2  2022         4
 3  2023         7
 4  2024         6
 5  2025         6
 6  2026         7

#by 20-year group
dd %>%
  group_by(year_20) %>%
  summarise(year20_freq = sum(drought)) %>%
  ungroup()

# A tibble: 4 x 2
  year_20   year20_freq
  <fct>           <dbl>
1 2021_2040         125
2 2041_2060         121
3 2061_2080         121
4 2081_2100         132

Расчет продолжительности засухи немного сложнее. Он включает

  1. , идентифицирующий первый месяц каждой засухи
  2. , вычисляющий продолжительность каждой засухи
  3. , объединяющий информацию из 1 и 2 вместе

Мы можем использовать lag, чтобы определить, когда месяц изменился с «без засухи» на «засуху». В этом случае нам нужен индекс, где значение в строке i отличается от значения в строке i-1

# find index of where values change. 
change.ind <- dd$drought != lag(dd$drought)
#use index to find drought start
drought.start <- dd[change.ind & dd$drought == 1,]

Это приводит к подмножеству начального набора данных, но только со строками с первый месяц засухи. Тогда мы можем использовать rle для расчета продолжительности засухи. rle будет вычислять длину каждого прогона чисел, поэтому нам нужно будет установить поднабор только тех прогонов, в которых значение == 1 (засуха)

#calculate drought lengths
drought.lengths <- rle(dd$drought)
# we only want droughts (values = 1)
drought.lengths <- drought.lengths$lengths[drought.lengths$values==1]

Теперь мы можем объединить эти два фрагмента информации все вместе. Первая строка - NA, потому что в i-1 нет значения для сравнения задержки. Его можно удалить, если вы не хотите включать эти данные.

drought.dur <- cbind(drought.start, drought_length = drought.lengths)
head(drought.dur)
         Date        spei year   year_20 drought drought_length
NA       <NA>          NA   NA      <NA>      NA              2
5  2021-05-01 -0.47325008 2021 2021_2040       1              1
9  2021-09-01 -2.04564549 2021 2021_2040       1              1
11 2021-11-01 -1.04293866 2021 2021_2040       1              2
14 2022-02-01 -0.83759671 2022 2021_2040       1              1
17 2022-05-01 -0.07784316 2022 2021_2040       1              1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...