Я думаю, что у меня есть рабочее решение для этого (хотя оно еще не учитывает другие name
с) - это кажется довольно сложной проблемой. Это, вероятно, не особенно эффективное решение, так как он находит одну строку для свертывания, сворачивает ее, а затем снова проверяет весь набор данных и проходит через процесс, пока не останется больше строк для свертывания. Если есть более эффективные способы сделать это, я бы хотел увидеть их:
# Identify which rows are "between" rows that can be collapsed
get_between_info = function(data) {
data %>%
mutate(outer_row = value == 1 & num >= 1,
inner_row = value == 0 & num == 1,
between_row = inner_row & lead(outer_row) & lag(outer_row))
}
df = df %>%
get_between_info()
while (any(df$between_row)) {
collapse_group = which(df$between_row)[1] + c(-1, 0, 1)
collapsed = summarise(df[collapse_group, ],
name = first(name),
value = 1,
group = first(group),
num = sum(num),
range = paste0(
str_split(range[1], "-")[[1]][1],
"-",
str_split(range[n()], "-")[[1]][2]
))
before = df %>% filter(row_number() < collapse_group[1])
after = df %>% filter(row_number() > collapse_group[3])
df = bind_rows(before, collapsed, after)
df = df %>% get_between_info()
}
Вывод (я не понимаю логику определения чисел group
, поэтому мои отличаются):
> df
name value group num range outer_row inner_row between_row
1 A 1 1 14 Jan2000-Feb2001 TRUE FALSE FALSE
2 A 0 6 9 March2001-Nov2001 FALSE FALSE FALSE
3 A 1 7 3 Dec2001-Feb2002 TRUE FALSE FALSE
4 A 0 10 2 March2002-April2002 FALSE FALSE FALSE
Свернувшийся код, вероятно, можно было бы очистить, сначала разбив столбец range
на отдельные столбцы range_start
и range_end
(перед началом любого из этих процессов) - это сделало бы генерацию свернутого df намного чище.