Как вывести максимальное значение в диапазоне строк во фрейме данных? - PullRequest
0 голосов
/ 13 января 2019

Предположим, у меня есть следующие данные и фрейм данных:

sample_data <- c(1:14)
sample_data2 <- c(NA,NA,NA, "break", NA, NA, "break", NA,NA,NA,NA,NA,NA,"break")
sample_df <- as.data.frame(sample_data)
sample_df$sample_data2 <- sample_data2

Когда я печатаю этот фрейм данных, результаты выглядят следующим образом:

   sample_data sample_data2
1            1         <NA>
2            2         <NA>
3            3         <NA>
4            4        break
5            5         <NA>
6            6         <NA>
7            7        break
8            8         <NA>
9            9         <NA>
10          10         <NA>
11          11         <NA>
12          12         <NA>
13          13         <NA>
14          14        break

Как бы я запрограммировал его так, чтобы при каждом "разрыве" он выводил максимум из этого ряда вверх? Например, я бы хотел, чтобы код выводил набор (4,7,14). Кроме того, я бы хотел, чтобы он находил максимальное значение только до следующего интервала «перерыва». Я заранее прошу прощения, если использовал неверную номенклатуру.

Ответы [ 5 ]

0 голосов
/ 13 января 2019

В зависимости от того, хотите ли вы оценить максимальное число «sample_data» между всеми «sample_data2» == break, включая (например, строка 1 - строка 4), или исключить (например, строка 1 - строка 3) заданный «sample_data2» == break строка, вы можете сделать что-то подобное с tidyverse:

За исключением строк разрыва:

sample_df %>%
 group_by(sample_data2) %>%
 mutate(temp = ifelse(is.na(sample_data2), NA_character_,  paste0(gl(length(sample_data2), 1)))) %>%
 ungroup() %>%
 fill(temp, .direction = "up") %>%
 filter(is.na(sample_data2)) %>%
 group_by(temp) %>%
 summarise(res = max(sample_data))

  temp    res
  <chr> <dbl>
1 1        3.
2 2        6.
3 3       13.

Включая строки разрыва:

sample_df %>%
 group_by(sample_data2) %>%
 mutate(temp = ifelse(is.na(sample_data2), NA_character_,  paste0(gl(length(sample_data2), 1)))) %>%
 ungroup() %>%
 fill(temp, .direction = "up") %>%
 group_by(temp) %>%
 summarise(res = max(sample_data)) 

  temp    res
  <chr> <dbl>
1 1        4.
2 2        7.
3 3       14.

Оба кода создают переменную ID, называемую "temp", используя gl() для "sample_data2" == break, а затем заполняют строки NA этим идентификатором. Затем первый код отфильтровывает строки «sample_data2» == break и оценивает максимальные значения «sample_data» на группу, а второй оценивает максимальные значения «sample_data» на группу, включая «sample_data2» == строки разрыва.

0 голосов
/ 13 января 2019

Похоже, есть много разных способов сделать это. Вот как я это сделал:

rows <- which(sample_data2 == "break") #Get the row indices for where "break" appears

findmax <- function(maxrow) {

  max(sample_data[1:maxrow])

} #Create a function that returns the max "up to" a given row

sapply(rows, findmax) #apply it for each of your rows

### [1]  4  7 14

Обратите внимание, что это работает "до" данной строки. Получить максимальное значение между двумя перерывами, вероятно, было бы проще с одним из других решений, но вы также можете сделать это, посмотрев строку j-1 в строку j от объекта rows.

0 голосов
/ 13 января 2019

У меня есть ответ, используя data.table:

library(data.table)

sample_df <- setDT(sample_df)
sample_df[,group := (rleid(sample_data2)-0.5)%/%2]
sample_df[,.(maxvalues = max(sample_data)),by = group]

   group maxvalues
1:     0         4
2:     1         7
3:     2        14

Сложная часть: (rleid(sample_data2)-0.5)%/%2: rleid создает увеличивающийся индекс для каждого изменения:

    sample_data sample_data2 rleid
 1:           1           NA     1
 2:           2           NA     1
 3:           3           NA     1
 4:           4        break     2
 5:           5           NA     3
 6:           6           NA     3
 7:           7        break     4
 8:           8           NA     5
 9:           9           NA     5
10:          10           NA     5
11:          11           NA     5
12:          12           NA     5
13:          13           NA     5
14:          14        break     6

Если вы сохраняете всю часть этого индекса - 0,5, у вас есть постоянный индекс для нужных вам строк, который вы можете использовать для операции группировки:

    sample_data sample_data2 group
 1:           1           NA     0
 2:           2           NA     0
 3:           3           NA     0
 4:           4        break     0
 5:           5           NA     1
 6:           6           NA     1
 7:           7        break     1
 8:           8           NA     2
 9:           9           NA     2
10:          10           NA     2
11:          11           NA     2
12:          12           NA     2
13:          13           NA     2
14:          14        break     2

Тогда это просто максимум для каждой группы. Вы можете легко перевести его на dplyr, если вам проще

0 голосов
/ 13 января 2019

Вот два способа с базой R. Хитрость в том, чтобы определить переменную группировки, grp.

grp <- !is.na(sample_df$sample_data2) & sample_df$sample_data2 == "break"
grp <- rev(cumsum(rev(grp))) 
grp <- -1*grp + max(grp)

tapply(sample_df$sample_data, grp, max, na.rm = TRUE)
aggregate(sample_data ~ grp, sample_df, max, na.rm = TRUE)

Данные.
Это упрощенный код создания данных.

sample_data <- 1:14
sample_data2 <- c(NA,NA,NA, "break", NA, NA, "break", NA,NA,NA,NA,NA,NA,"break")
sample_df <- data.frame(sample_data, sample_data2)
0 голосов
/ 13 января 2019

Я строю группы, ища слово "break", а затем перемещаю результаты на одну строку вверх. Затем некоторые dplyr команды, чтобы получить максимум каждой группы.

library(dplyr)
sample_df_new <- sample_df %>% 
  mutate(group = c(1, cumsum(grepl("break", sample_data2)) + 1)[1:length(sample_data2)]) %>% 
  group_by(group) %>% 
  summarise(group_max = max(sample_data))

> sample_df_new
# A tibble: 3 x 2
  group group_max
  <dbl>     <dbl>
1     1         4
2     2         7
3     3        14
...