假设我有以下数据和数据框:
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)的集合。另外,我希望它能仅找到下一个“中断”间隔之间的最大值。 如果我使用了不正确的术语,我事先表示歉意。
答案 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)%/%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
答案 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”值。>