我有一個包含數千行的資料框,我需要輸出屬于同一組和類的資料部分的最小值和最大值。我需要的是讀取第一個起始值,將其與結束列中的前一個值進行比較,如果較小,則跳轉到下一行依此類推,直到起始值大于前一個結束值,然后輸出最小起始值該部分的值和最大值。我的資料已經按 group-class-start-end 排序。
df <- data.frame(group = c("1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"),
class = c("2", "2", "2", "2", "2", "2", "2", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3"),
start = c("23477018","23535465","23567386","24708741","24708741","24708741","48339885","87274","87274","127819","1832772","1832772","1832772","6733569","7005524","7005524","7644572","8095433","8095433","8095433"),
end = c("47341413", "47341413", "47909872","42247834","47776347","47909872","53818713","3161655","3479466","3503792","3503792","4916249","5329014","8089225","12037894","13934484","12037894","12037894","13626119","13934484"))
我想要實作的輸出是:
group class start end
1 1 2 23477018 47909872
2 1 2 48339885 53818713
3 1 3 87274 5329014
4 1 3 6733569 13934484
任何關于如何實作這一目標的想法將不勝感激。
uj5u.com熱心網友回復:
我為此使用了 data.table。
我的方法是首先將開始和結束更改為整數,否則會出現排序問題。
找出哪些行滿足 start > max(all previous end),然后使用 cumsum 給出遞增的子組編號。
然后它只是一個簡單的子組的最小值和最大值。
沒有回圈可以盡可能快地做到這一點。
library(data.table)
df <- data.frame(group = c("1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"),
class = c("2", "2", "2", "2", "2", "2", "2", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3"),
start = c("23477018","23535465","23567386","24708741","24708741","24708741","48339885","87274","87274","127819","1832772","1832772","1832772","6733569","7005524","7005524","7644572","8095433","8095433","8095433"),
end = c("47341413", "47341413", "47909872","42247834","47776347","47909872","53818713","3161655","3479466","3503792","3503792","4916249","5329014","8089225","12037894","13934484","12037894","12037894","13626119","13934484"))
setDT(df)
df[, c('start', 'end') := lapply(.SD, as.integer), .SDcols = c('start', 'end')]
df[, subgrp := cumsum(start > shift(cummax(.SD$end), fill = 0)), keyby = c('group', 'class')]
ans <- df[, .(start = min(start), end = max(end)), keyby = c('group', 'class', 'subgrp')]
ans[, subgrp := NULL][]
group class start end
1: 1 2 23477018 47909872
2: 1 2 48339885 53818713
3: 1 3 87274 5329014
4: 1 3 6733569 13934484
uj5u.com熱心網友回復:
這是一個tidyverse解決方案:
library(tidyverse)
df <- data.frame(
group = c("1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"),
class = c("2", "2", "2", "2", "2", "2", "2", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3", "3"),
start = c("23477018","23535465","23567386","24708741","24708741","24708741","48339885","87274","87274","127819","1832772","1832772","1832772","6733569","7005524","7005524","7644572","8095433","8095433","8095433"),
end = c("47341413", "47341413", "47909872","42247834","47776347","47909872","53818713","3161655","3479466","3503792","3503792","4916249","5329014","8089225","12037894","13934484","12037894","12037894","13626119","13934484"))
df %>%
group_by(group, class) %>%
mutate(
start = as.integer(start),
end = as.integer(end),
end_lag = lag(end),
larger_flag = case_when(start > end_lag & !is.na(end_lag) ~ 1, TRUE ~ 0),
sub_group = cumsum(larger_flag)) %>%
group_by(group, class, sub_group) %>%
summarise(
start = min(start),
end = max(end),
.groups = 'drop'
) %>%
select(-sub_group)
# A tibble: 4 x 4
group class start max
<chr> <chr> <int> <int>
1 1 2 23477018 47909872
2 1 2 48339885 53818713
3 1 3 87274 5329014
4 1 3 6733569 13934484
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/368642.html
上一篇:使用蠻力在方形2D陣列中找到峰值的最簡單或最佳方法是什么?
下一篇:如何解釋這個圖函式演算法?
