Если предыдущая и следующая строки совпадают, добавьте полный предыдущий столбец - PullRequest
1 голос
/ 02 июля 2019

У меня есть data.table, я хочу использовать Id в качестве другой группы, и разница между секундами между предыдущей и следующей строками превышает 300.

Автоматически добавлять новый столбец, а также содержимое предыдущего столбца, и можно судить о необходимости добавить несколько столбцов на основе разницы в количестве секунд между двумя столбцами

DT <-data.table(Id = c("A","A","A","A","A","B","B","B","B"),
                valueA = c(479117,479119,479117,479118,479118,479118,479118,479118,479121),
                valueB = c(209946,209948,209946,209953,209953,209953,209953,209951,209944),
                second = c(0,745,12,5,50,938,114,339,705))

Тест данных кадра

     Id   valueA   valueB   second
 1   A    479117   209946     0
 2   A    478419   209948   745 
 3   A    479117   209946    12
 4   A    479118   209953     5
 5   A    479118   209953    50
 6   B    479118   209953   938
 7   B    479118   209953   114
 8   B    479118   209951   339
 9   B    479121   209944   705

Мне бы хотелось, чтобы преобразованный кадр данных выглядел следующим образом

     Id   valueA   valueB   second
 1   A    479117   209946     0  #(original row 1)
#2   A    479117   209946   300  #(new row 2)
#3   A    479117   209946   300  #(new row 3)
 4   A    478419   209948   745  #(original row 2)
 5   A    479117   209946    12  #(original row 3)
 6   A    479118   209953     5
 7   A    479118   209953    50  #(original row 5)
 Because original row 5 and original row 6 Id is not the same, so don't compare
 8   B    479118   209953   938  #(original row 6)
 9   B    479118   209953   114
 10  B    479118   209951   339  #(original row 8)
#11  B    479118   209951   300  #(new row 11)
 12  B    479121   209944   705  #(original row 9)

Поскольку количество секунд между исходной строкой 1 и исходной строкой 2 равно 745, новая строка 2 и новая строка 3 скопируютсодержимое предыдущего ряда.Почему вы хотите выполнить копирование дважды, потому что 745/300 = 2,48 (округление), берите дважды

Число секунд между исходной строкой 8 и исходной строкой 9 равно 366, поэтому новая строка 11 будет копировать содержимоепредыдущий ряд (8).Почему вы хотите скопировать его один раз, потому что 366/300 = 1,22, возьмите его один раз (Раунд)

Мои исходные данные содержат два миллиона столбцов

Описание очень сложное.Я не знаю, есть ли способ сделать это?

Спасибо.

1 Ответ

0 голосов
/ 04 июля 2019

Поскольку никто не придумал умного решения, я дам вам несколько не элегантный, но, вероятно, рабочий подход:

library(dplyr)
library(purrr)

grow_df <- function(x) {
  seconds <- DT %>% 
    filter(Id == x) %>% 
    pull(second)

  seconds2 <- c()
  for (i in seq(along = seconds)) {
    if (i == 1 || (i > 1 & seconds[i] - seconds[i - 1] <= 300)) {
      seconds2 <- c(seconds2, seconds[i])
    } else {
      for(j in 1:floor((seconds[i] - seconds[i - 1]) / 300)) {
        seconds2 <- c(seconds2, 300)
      }
      seconds2 <- c(seconds2, seconds[i])
    }
  }
  return(tibble(Id = x, second = seconds2))
}

map(DT$Id %>% unique, grow_df) %>% 
  bind_rows() %>% 
  left_join(DT, by = c("Id", "second")) %>% 
  fill(valueA, valueB) %>% 
  select(Id, valueA, valueB, second)

Примечание. Из соображений производительности не следует «наращивать» вектор, как я сделал с seconds2. Но это эффективно для примера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...