Редактировать: Вот ленивый подход, который все еще должен быть очень быстрым, за счет временного создания строк, которые мы удалим в конце.Вместо того чтобы выяснить, сколько копий нужно сделать для каждой строки, я делаю несколько копий каждой строки, затем применяю быстрые векторизованные вычисления, чтобы получить обновленные значения end
, count
и count0
, и удаляю строкинам не нужно.
library(dplyr); library(tidyr)
output <-
dat %>%
mutate(orig_row = row_number()) %>%
uncount(10) %>% # I'm assuming here that 10 is enough columns
group_by(orig_row) %>%
mutate(row = row_number()) %>%
mutate(
end = end + row,
count0 = pmin(count, start * para1 + end * para2), # Edit #2
count = count - cumsum(count0)
) %>%
filter(lag(count, default = 0) >= 0) %>%
mutate(count = pmax(0, count),
count0 = if_else(count == 0, lag(count), count0))
output
# A tibble: 4 x 10
# Groups: orig_row [2]
region place start end count para1 para2 orig_row row count0
<chr> <chr> <int> <int> <dbl> <dbl> <dbl> <int> <int> <dbl>
1 A C 2 7 6.02 0.394 2.46 1 1 18.0
2 A C 2 8 0 0.394 2.46 1 2 6.02
3 A D 3 2 5.34 0.644 2.86 2 1 7.66
4 A D 3 3 0 0.644 2.86 2 2 5.34
Первоначальный ответ:
Я предполагаю, что это по соседству.
Предостережение: я не получил то же самоекак показано в примере данных, и я не понимаю, каким образом конкретные числа в предоставленном образце приведут к предлагаемым результатам.Например, из первой строки dat
, которую вы показываете (отличной от той, что была у меня), первый count0 должен быть 2*0.394 + 6*2.456 = 15.527
, нет?
Мой подход заключается в том, чтобы вычислить count0
, а затем вычислитьсколько из count
вписывается в него, затем сделайте столько копий строки, уменьшив count
на count0
с каждой строки.
library(dplyr); library(tidyr)
output <- dat %>%
mutate(end = end + 1,
orig_data = row_number(),
count0 = if_else(count == 0, 0,
start*para1 + end*para2),
copies = 1 + count %/% count0) %>%
uncount(copies) %>%
group_by(orig_data) %>%
mutate(row = row_number() - 1,
count = count - row * count0)
Кстати, мой dat
инициализируется по-разному, используя set.seed(71)
.Не могли бы вы подтвердить, если ваши данные инициализируются, как указано в ОП?Выровнять будет легче, если мы начнем с того же места.
> head(dat)
region place start end count para1 para2
1: A C 2 7 19 3.400587 2.757140
2: A D 3 3 31 1.503740 6.089518
3: A C 2 8 2 2.561869 5.236298
4: A D 2 3 33 3.069835 3.770121
5: A C 2 2 21 2.989221 3.547926
6: A D 5 5 32 2.720636 5.379352