如何在数据框中的行范围内输出最大值?

时间:2019-01-12 21:39:56

标签: r dataframe max filtering

假设我有以下数据和数据框:

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 :(得分:2)

我构建寻找“ 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

答案 1 :(得分:2)

我有一个使用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)%/%2rleid为每个更改创建一个递增索引:

    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

答案 2 :(得分:1)

有两种使用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)

答案 3 :(得分:1)

看起来有很多不同的方法可以做到这一点。这是我的处理方式:

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

请注意,这可以“最多”给定行。使用其他解决方案之一来获得两次中断之间的最大值可能会更容易,但是您也可以通过查看rows对象的第j-1行到第j行来实现。

答案 4 :(得分:1)

取决于您是否要评估所有“ sample_data2”之间的最大“ sample_data”数目==包括(例如,第1行至第4行)的中断或排除(例如,第1至第3行)给定的“ sample_data2” ==中断行,您可以使用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.

这两个代码都使用gl()为“ sample_data2” == break创建一个名为“ temp”的ID变量,然后用该ID填充NA行。然后,第一个代码过滤掉“ sample_data2” ==中断行并评估每组的最大“ sample_data”值,而第二个代码评估每组包括“ sample_data2” ==中断行的最大“ sample_data”值。