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

Данные
Давайте посмотрим на простой набор данных (у меня на самом деле> 200 000 строк):

df <- data.frame(
  id = c(rep(1, 11), rep(2,6)),
  ref.pos = c(NA,NA,NA,301,302,303,800,801,NA,NA,NA, 500,501,502, NA, NA, NA),
  pos     = c(1:11, 30:35)
)

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

   id ref.pos pos
1   1      NA   1
2   1      NA   2
3   1      NA   3
4   1     301   4
5   1     302   5
6   1     303   6
7   1     800   7
8   1     801   8
9   1      NA   9
10  1      NA  10
11  1      NA  11
12  2     500  30
13  2     501  31
14  2     502  32
15  2      NA  33
16  2      NA  34
17  2      NA  35

Чего я хочу достичь
За id Я хочу расширить числа в ref.pos, чтобы заполнить весь столбец, где ref.pos числа go вниз двигаться вверх в кадре данных и вверх двигаться вниз в столбце. Это может привести к следующему кадру данных:

   id ref.pos pos
1   1     298   1
2   1     299   2
3   1     300   3
4   1     301   4
5   1     302   5
6   1     303   6
7   1     800   7
8   1     801   8
9   1     802   9
10  1     803  10
11  1     804  11
12  2     500  30
13  2     501  31
14  2     502  32
15  2     503  33
16  2     504  34
17  2     505  35

То, что я пытался
Я бы sh Я мог бы предоставить здесь некоторый код, однако я не нашел правильного Кстати, за два дня, особенно это не относится к большим наборам данных. Я нашел df %>% group_by(id) %>% tidyr::fill(ref.pos, .direction = "downup") интересным, однако это повторяет цифры, а не идет вниз и вверх для меня.

Я надеюсь, что мой вопрос ясен, в противном случае, дайте мне знать в комментариях!

Ответы [ 2 ]

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

Опция с использованием data.table:

fillends <- function(x) nafill(nafill(x, "locf"), "nocb")

setDT(df)[, ref.pos2 := {
    dif <- fillends(c(diff(ref.pos), NA_integer_))
    frp <- fillends(ref.pos)
    fp <- fillends(replace(pos, is.na(ref.pos), NA_integer_))
    fifelse(is.na(ref.pos), frp + dif*(pos - fp), ref.pos)
}, id]

Выход:

    id ref.pos pos ref.pos2
 1:  1      NA   1      298
 2:  1      NA   2      299
 3:  1      NA   3      300
 4:  1     301   4      301
 5:  1     302   5      302
 6:  1     303   6      303
 7:  1     802   7      802
 8:  1     801   8      801
 9:  1      NA   9      800
10:  1      NA  10      799
11:  1      NA  11      798
12:  2     500  30      500
13:  2     501  31      501
14:  2     502  32      502
15:  2      NA  33      503
16:  2      NA  34      504
17:  2      NA  35      505

данные:

df <- data.frame(
    id = c(rep(1, 11), rep(2,6)),
    ref.pos = c(NA,NA,NA,301,302,303,802,801,NA,NA,NA, 500,501,502, NA, NA, NA),
    pos     = c(1:11, 30:35)
)
1 голос
/ 27 апреля 2020

Базовая опция R - это определение пользовательской функции fill, которая применяется в ave

fill <- function(v) {
  inds <- range(which(!is.na(v)))
  l <- 1:inds[1]
  u <- inds[2]:length(v)
  v[l] <- v[inds[1]] - rev(l)+1
  v[u] <- v[inds[2]] + seq_along(u)-1
  v
}

df <- within(df,ref.pos <- ave(ref.pos,id,FUN = fill))

так, что

> df
   id ref.pos pos
1   1     298   1
2   1     299   2
3   1     300   3
4   1     301   4
5   1     302   5
6   1     303   6
7   1     800   7
8   1     801   8
9   1     802   9
10  1     803  10
11  1     804  11
12  2     500  30
13  2     501  31
14  2     502  32
15  2     503  33
16  2     504  34
17  2     505  35
...