В R переберите один кадр данных, чтобы сгенерировать другой кадр данных, условно с одной или несколькими строками для каждой строки в первом кадре данных - PullRequest
0 голосов
/ 15 мая 2019

У меня есть такой набор данных:

set.seed(71)
dat <- data.table(region = rep(c('A','B'), each=10),
    place = rep(c('C','D'), 10),
    start = sample.int(5, 20, replace = TRUE),
    end = sample.int(10, 20, replace = TRUE),
    count = sample.int(50, 20, replace = TRUE),
    para1 = rnorm(20,3,1),
    para2 = rnorm(20,4,1))

Я хотел бы пройтись по этим данным, чтобы условно сгенерировать другую таблицу со следующими столбцами: регион, место, начало, конец, число, число0 с потенциальноболее одной строки для каждой строки в dat.в новой таблице данные для области, места и начала столбцов будут скопированы из dat, а данные для столбцов end, count и count0 будут сгенерированы.

Вот правила для перебора каждой строкиof dat:

end = end +1
if (count=0) {
  count0=0
} else {
  count0=start*para1 + end*para2
}
if (count0>count) {
  count0=count
}
count = count -count0

Я пытался использовать комбинацию цикла for, оператора if и mutate, но не смог сделать это правильно.

Я ожидаю получить такую ​​таблицу после прохождения первых двух строк данных:

region  place   start   end       count         count0
     A      C       2     7  6.01673062    17.98326938
     A      C       2     8           0     6.01673062
     A      D       3     2  5.34392419     7.65607581
     A      D       3     3           0     5.34392419


the first two rows of dat I have are:
region  place   start   end count   para1         para2
     A      C       2     6    24   0.39412969  2.45643
     A      D       3     1    13   0.64372127  2.862456

1 Ответ

0 голосов
/ 16 мая 2019

Редактировать: Вот ленивый подход, который все еще должен быть очень быстрым, за счет временного создания строк, которые мы удалим в конце.Вместо того чтобы выяснить, сколько копий нужно сделать для каждой строки, я делаю несколько копий каждой строки, затем применяю быстрые векторизованные вычисления, чтобы получить обновленные значения 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...