Для каждой строки кадра данных добавьте x строк, где x получается из этой строки - PullRequest
0 голосов
/ 07 ноября 2018

У меня есть data.frame, к которому мне нужно добавить строки, но количество добавляемых строк (и их содержимое) определяется из существующих строк data.frame. Я также хотел бы закончить столбцом, перечисляющим строки каждой дублированной группы. Вот пример данных:

> A <- data.frame(veh = c("MINIVAN","HEAVY TRUCK"),age = c(2.5,3.5),rows_to_add = c(2,3))
> A
          veh age rows_to_add
1     MINIVAN 2.5           2
2 HEAVY TRUCK 3.5           3

и желаемый результат:

> B <- rbind(do.call("rbind",replicate(n=unique(A[1,"rows_to_add"])+1,A[1,],simplify = FALSE)),
+ do.call("rbind",replicate(n=unique(A[2,"rows_to_add"])+1,A[2,],simplify = FALSE)))
> B <- cbind(B,enum = c(0:2,0:3))
> B
           veh age rows_to_add enum
1      MINIVAN 2.5           2    0
2      MINIVAN 2.5           2    1
3      MINIVAN 2.5           2    2
24 HEAVY TRUCK 3.5           3    0
21 HEAVY TRUCK 3.5           3    1
22 HEAVY TRUCK 3.5           3    2
23 HEAVY TRUCK 3.5           3    3

Очевидно, что код, который я использовал здесь для генерации вывода, является грязным, не масштабируемым и, возможно, неэффективным. Я ищу общее решение, которое позволило бы мне делать это с большим data.frame с разумной скоростью и избегать циклов (попытка ускорить загрузочный код является частью импульса для этого вопроса).

Этот вопрос касается более слабой версии проблемы, в которой число или добавляемые строки не зависят от строк самих данных, а вставляемые строки могут содержать NA s, но я не нашел способа обобщить ответ там.

Как мне добиться желаемого результата в целом?

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

A base R подход

out <- A[rep(seq_len(nrow(A)), A$rows_to_add + 1), ]
out
#            veh age rows_to_add
#1       MINIVAN 2.5           2
#1.1     MINIVAN 2.5           2
#1.2     MINIVAN 2.5           2
#2   HEAVY TRUCK 3.5           3
#2.1 HEAVY TRUCK 3.5           3
#2.2 HEAVY TRUCK 3.5           3
#2.3 HEAVY TRUCK 3.5           3

Добавьте новый столбец способом, предложенным @thelatemail в комментариях.

out$enum <- sequence(unique(A$rows_to_add) + 1) - 1
#out <- transform(out, enum = ave(age, rows_to_add, FUN = seq_along) - 1) # my slower attempt
#            veh age rows_to_add enum
#1       MINIVAN 2.5           2    0
#1.1     MINIVAN 2.5           2    1
#1.2     MINIVAN 2.5           2    2
#2   HEAVY TRUCK 3.5           3    0
#2.1 HEAVY TRUCK 3.5           3    1
#2.2 HEAVY TRUCK 3.5           3    2
#2.3 HEAVY TRUCK 3.5           3    3

Потенциально более быстрая альтернатива с data.table

library(data.table)
setDT(A)
out <- A[rep(seq_len(dim(A)[1]), A[, rows_to_add] + 1)
         ][, enum := sequence(unique(rows_to_add) + 1) - 1]
out
0 голосов
/ 07 ноября 2018

Вам нужно uncount от tidyr -

library(dplyr)
library(tidyr)

A %>% 
  uncount(weights = rows_to_add + 1, .id = "enum") %>%
  mutate(
    enum = enum - 1
  )

          veh age rows_to_add enum
1     MINIVAN 2.5           2    0
2     MINIVAN 2.5           2    1
3     MINIVAN 2.5           2    2
4 HEAVY TRUCK 3.5           3    0
5 HEAVY TRUCK 3.5           3    1
6 HEAVY TRUCK 3.5           3    2
7 HEAVY TRUCK 3.5           3    3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...