r语言 - 如何在数据框中的行范围内输出最大值



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

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) 集。此外,我希望它只找到下一个"中断"间隔之间的最大值。如果我使用了任何不正确的命名法,我提前道歉。

我构建了寻找单词"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

我有一个答案,使用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<</p>

div class="ans>

以下是使用 base R 的 2 种方法。诀窍是定义一个分组变量,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)

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

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 行来做到这一点。

根据您是否要评估所有"sample_data2"== 中断(例如第 1 行到第 4 行)或排除(例如第 1 行到第 3 行)给定的"sample_data2"== 中断行之间的最大"sample_data"数字,您可以使用 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"==中断,然后使用该ID填充NA行,从而创建一个名为"temp"的ID变量。然后,第一个代码过滤掉"sample_data2"==中断行并评估每组的最大"sample_data"值,而第二个代码评估每组的最大"sample_data"值,包括"sample_data2"==中断行。

最新更新