Расширить диапазон номеров до отдельных номеров - PullRequest
0 голосов
/ 22 апреля 2020

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


Допустим, у нас есть этот фрейм данных:

Набор данных

df <- data.frame(start = c(10, 20), end = c(15,33), label = c('ex1','ex2'))

Что выглядит следующим образом:

  start end label
1    10  15   ex1
2    20  33   ex2


Что я хочу получить
Я хочу расширить с start -> end, вот так:

  pos label
1   10   ex1
2   11   ex1
3   12   ex1
4   13   ex1
5   14   ex1
6   15   ex1
7   20   ex2
8   21   ex2
9   22   ex2
10  23   ex2
11  24   ex2
12  25   ex2
13  26   ex2
14  27   ex2
15  28   ex2
16  29   ex2
17  30   ex2
18  31   ex2
19  32   ex2
20  33   ex2

Что у меня сейчас

f <- function(x) {data.frame(pos = x$start:x$end, label = x$label)}
df %>% rowwise() %>% do(f(.))

Пока работает мое решение, мой оригинал набор данных намного больше и сомневаюсь, что это эффективно. Более того, я хочу включить больше столбцов, чем label, поэтому я хочу переобучить все столбцы и просто разложить start и end

1 Ответ

1 голос
/ 22 апреля 2020

Я имею в виду решение data.table.

Я выдвинул гипотезу, что ваш label var уникален наблюдением. В противном случае вам следует использовать номер строки для группировки ваших данных.

library(data.table)
df <- data.frame(start = c(10, 20), end = c(15,33), label = c('ex1','ex2'))
setDT(df)

df[, seq(.SD[['start']], .SD[['end']]), by = label]
label V1
 1:   ex1 10
 2:   ex1 11
 3:   ex1 12
 4:   ex1 13
 5:   ex1 14
 6:   ex1 15
 7:   ex2 20
 8:   ex2 21
 9:   ex2 22
10:   ex2 23
11:   ex2 24
12:   ex2 25
13:   ex2 26
14:   ex2 27
15:   ex2 28
16:   ex2 29
17:   ex2 30
18:   ex2 31
19:   ex2 32
20:   ex2 33

С точки зрения эффективности, может быть трудно найти решение быстрее, чем data.table, предназначенное для этой цели.

Если вы не можете использовать label в качестве уникального идентификатора, вы можете сделать

df[,'rn' := seq(.N)]

df[, seq(.SD[['start']], .SD[['end']]), by = c('rn','label')]
    rn label V1
 1:  1   ex1 10
 2:  1   ex1 11
 3:  1   ex1 12
 4:  1   ex1 13
 5:  1   ex1 14
 6:  1   ex1 15
 7:  2   ex2 20
 8:  2   ex2 21
 9:  2   ex2 22
10:  2   ex2 23
11:  2   ex2 24
12:  2   ex2 25
13:  2   ex2 26
14:  2   ex2 27
15:  2   ex2 28
16:  2   ex2 29
17:  2   ex2 30
18:  2   ex2 31
19:  2   ex2 32
20:  2   ex2 33

и вы можете удалить номер промежуточной строки, используя df[,'rn' := NULL]

Эффективность

data.table приносит хорошее ускорение (не имеет большого значения, если вы используете один или два столбца для группировки в этом примере)

Unit: microseconds
                                                           expr      min       lq     mean   median       uq
                                  df %>% rowwise() %>% do(f(.)) 1549.408 1808.669 2309.332 2292.525 2555.888
          df[, seq(.SD[["start"]], .SD[["end"]]), by = "label"] 1011.608 1302.249 1555.808 1490.542 1779.543
 df[, seq(.SD[["start"]], .SD[["end"]]), by = c("label", "rn")]  968.124 1095.703 1387.556 1253.023 1592.483
      max neval cld
 7141.964   100   b
 3061.487   100  a 
 2953.598   100  a 

Если вы хотите go еще быстрее, вы можно установить ключ (?setkeyv). Если ваш фрейм данных имеет значительный размер, это может привести к значительному увеличению производительности (в этом небольшом примере это не так)

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