Растопить или реплицировать строки в таблице данных определенное количество раз и включить счетчик в R - PullRequest
0 голосов
/ 05 июня 2018

Я хотел бы «развернуть» фрейм данных, продублировав информацию в некоторых столбцах количество раз, указанное в пятом столбце.

Что было бы наиболее эффективным для достижения этой задачи с помощью R?(Открыть в таблицу данных или Dplyer, изменить форму решения).

Исходный кадр данных / таблица данных:

   f_1 f_2        d_1        d_2 i_1
1:   1   A 2016-01-01       <NA>  NA
2:   2   A 2016-01-02       <NA>  NA
3:   2   B 2016-01-03 2016-01-01   2
4:   3   C 2016-01-04       <NA>  NA
5:   4   D 2016-01-05 2016-01-02   5

Требуемый кадр данных / таблица данных

    f_1 f_2        d_1        d_2 i_1
 1:   1   A 2016-01-01       <NA>  NA
 2:   2   A 2016-01-02       <NA>  NA
 3:   2   B 2016-01-03 2016-01-01   1
 4:   2   B 2016-01-03 2016-01-01   2
 5:   3   C 2016-01-04       <NA>  NA
 6:   4   D 2016-01-05 2016-01-02   1
 7:   4   D 2016-01-05 2016-01-02   2
 8:   4   D 2016-01-05 2016-01-02   3
 9:   4   D 2016-01-05 2016-01-02   4
10:   4   D 2016-01-05 2016-01-02   5

Воспроизводимые данные:

DT <- data.table(
  f_1 = factor(c(1,2,2,3,4)),
  f_2 = factor(c("A", "A", "B", "C", "D")),
  d_1 = as.Date(c("2016-01-01","2016-01-02","2016-01-03","2016-01-04","2016-01-05")),
  d_2 = as.Date(c(NA,NA,"2016-01-01",NA,"2016-01-02")),
  i_1 = as.integer(c(NA,NA,2,NA,5)))

Спасибо и извините, если он дублируется.Я борюсь с подобными упражнениями.

Ответы [ 2 ]

0 голосов
/ 05 июня 2018

Вы в порядке, заменив i_1 на 1, когда NA?Если это так, следующее будет немного более читабельным:

Сначала повторите строки указанное количество раз ( ad hoc с учетом пропущенных значений i_1, используя replaceлюбезно предоставлено @Frank):

DT_out = DT[rep(1:.N, replace(i_1, is.na(i_1), 1L))]

Это может быть просто DT[rep(1:.N, i_1)], если мы уже заменили DT[is.na(i_1), i_1 := 1L].

Осталось только обновить значения i_1,Существуют более простые версии этого, в зависимости от ваших данных.Здесь я думаю, что это более общая версия:

DT_out[!is.na(i_1), i_1 := rowidv(.SD), .SDcols = !'i_1'][]
#     f_1 f_2        d_1        d_2 i_1
#  1:   1   A 2016-01-01       <NA>  NA
#  2:   2   A 2016-01-02       <NA>  NA
#  3:   2   B 2016-01-03 2016-01-01   1
#  4:   2   B 2016-01-03 2016-01-01   2
#  5:   3   C 2016-01-04       <NA>  NA
#  6:   4   D 2016-01-05 2016-01-02   1
#  7:   4   D 2016-01-05 2016-01-02   2
#  8:   4   D 2016-01-05 2016-01-02   3
#  9:   4   D 2016-01-05 2016-01-02   4
# 10:   4   D 2016-01-05 2016-01-02   5

rowid и rowidv дают номер строки в группах, определенных переменными, которые она передала.Вы можете сравнить с rowid(f_2), rowid(f_1) и rowid(f_1, f_2), чтобы понять, что я имею в виду.rowidv(.SD) является сокращением для rowid(f_1, f_2, d_1, d_2), поскольку мы исключаем i_1 из столбцов в .SD.

0 голосов
/ 05 июня 2018

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

DT[, .(i_1=if(!is.na(i_1)) seq_len(i_1) else i_1), 
    by=c(names(DT)[-ncol(DT)])]

вывод:

    f_1 f_2        d_1        d_2 i_1
 1:   1   A 2016-01-01       <NA>  NA
 2:   2   A 2016-01-02       <NA>  NA
 3:   2   B 2016-01-03 2016-01-01   1
 4:   2   B 2016-01-03 2016-01-01   2
 5:   3   C 2016-01-04       <NA>  NA
 6:   4   D 2016-01-05 2016-01-02   1
 7:   4   D 2016-01-05 2016-01-02   2
 8:   4   D 2016-01-05 2016-01-02   3
 9:   4   D 2016-01-05 2016-01-02   4
10:   4   D 2016-01-05 2016-01-02   5

Или другой способ, используя data.table,Для каждой строки создайте последовательность чисел с помощью i_1 и добавьте исходные данные к этой последовательности с помощью c(.SD[, -"i_1], ..... и, наконец, удалите столбец by

DT[, c(.SD[, -"i_1"], .(i_1=if (!is.na(i_1)) seq_len(i_1) else i_1)), 
    by=seq_len(DT[,.N])][,-1L]
...