Вставить N пустых строк в фрейм данных R, используя значение в столбце - PullRequest
1 голос
/ 01 мая 2020

У меня есть фрейм данных:

Var_1 = c("A","B","C","D","E","F","G","H")
Var_2 = c(0,1,0,2,1,0,0,1)
DF = data.frame(Var_1,Var_2)
print(DF)

 Var_1 Var_2
1     A     0
2     B     1
3     C     0
4     D     2
5     E     1
6     F     0
7     G     0
8     H     1

Мне нужно вставить N пустых строк, заполненных NA, во фрейм данных, используя значение, найденное в Var_2 определить N . Эти новые строки должны быть вставлены сразу после того, как значение Var_2 равно> = 1. Поэтому я хотел бы, чтобы мой фрейм данных выглядел так:

print(DF)

 Var_1 Var_2
1      A     0
2      B     1
3   <NA>    NA
4      C     0
5      D     2
6   <NA>    NA
7   <NA>    NA
8      E     0
9      F     0
10     G     0
11     H     1
12  <NA>    NA

Я застрял с этим, любая помощь будет принята с благодарностью. Спасибо.

Ответы [ 3 ]

4 голосов
/ 01 мая 2020

Последовательности и подмножества для спасения.
Дублирование каждой строки на Var_2 + 1 создает Var_2 дополнительных строк при значении > 0 и поддерживает строку при значении == 0
Затем вы можете использовать duplicated TRUE/FALSE в последовательности для замены только дополнительных строк на NA.

s <- rep(sequence(nrow(DF)), DF$Var_2 + 1)
DFnew <- DF[s,]
DFnew[duplicated(s),] <- NA
DFnew
#    Var_1 Var_2
#1       A     0
#2       B     1
#2.1  <NA>    NA
#3       C     0
#4       D     2
#4.1  <NA>    NA
#4.2  <NA>    NA
#5       E     1
#5.1  <NA>    NA
#6       F     0
#7       G     0
#8       H     1
#8.1  <NA>    NA

Это также должно быть довольно быстрым для всех, кроме самых массивных наборов данных.

# 800K records
DF <- DF[rep(1:8,1e5),]
system.time({
  s <- rep(sequence(nrow(DF)), DF$Var_2 + 1)
  DFnew <- DF[s,]
  DFnew[duplicated(s),] <- NA
})
#   user  system elapsed 
#  0.600   0.000   0.601
2 голосов
/ 01 мая 2020

Вы можете повторить каждую строку Var_2 раз и заменить duplicated строки на NA

library(dplyr)
DF1 <- DF %>% mutate(Var_3 = Var_2 + 1, row = row_number()) %>% 
             tidyr::uncount(Var_3)
DF1[duplicated(DF1$row), ] <- NA
DF1$row <- NULL

#    Var_1 Var_2
#1       A     0
#2       B     1
#2.1  <NA>    NA
#3       C     0
#4       D     2
#4.1  <NA>    NA
#4.2  <NA>    NA
#5       E     1
#5.1  <NA>    NA
#6       F     0
#7       G     0
#8       H     1
#8.1  <NA>    NA
2 голосов
/ 01 мая 2020

Интересная проблема:

ind <- which(DF$Var_2 > 0)
ind
# [1] 2 4 5 8
starts <- 1L + unique(c(0L, head(ind, n = -1)))
stops <- unique(c(ind, nrow(DF))) # in case the last !0 is not on bottom row
starts
# [1] 1 3 5 6
stops
# [1] 2 4 5 8
DFaug_list <- Map(
  function(a, b) rbind(DF[a:b,], DF[b,][rep(NA, DF$Var_2[b]), ]),
  starts, stops)

Теперь у нас есть список фреймов:

str(DFaug_list)
# List of 4
#  $ :'data.frame': 3 obs. of  2 variables:
#   ..$ Var_1: Factor w/ 8 levels "A","B","C","D",..: 1 2 NA
#   ..$ Var_2: int [1:3] 0 1 NA
#  $ :'data.frame': 4 obs. of  2 variables:
#   ..$ Var_1: Factor w/ 8 levels "A","B","C","D",..: 3 4 NA NA
#   ..$ Var_2: int [1:4] 0 2 NA NA
#  $ :'data.frame': 2 obs. of  2 variables:
#   ..$ Var_1: Factor w/ 8 levels "A","B","C","D",..: 5 NA
#   ..$ Var_2: int [1:2] 1 NA
#  $ :'data.frame': 4 obs. of  2 variables:
#   ..$ Var_1: Factor w/ 8 levels "A","B","C","D",..: 6 7 8 NA
#   ..$ Var_2: int [1:4] 0 0 1 NA

, и все, что нам нужно сделать, чтобы объединить их, это трюк с do.call или использовать функции из пакетов data.table или dplyr:

DFaug <- do.call(rbind.data.frame, DFaug_list)
DFaug
#      Var_1 Var_2
# 1        A     0
# 2        B     1
# NA    <NA>    NA
# 3        C     0
# 4        D     2
# NA1   <NA>    NA
# NA.1  <NA>    NA
# 5        E     1
# NA2   <NA>    NA
# 6        F     0
# 7        G     0
# 8        H     1
# NA3   <NA>    NA
DFaug <- data.table::rbindlist(DFaug_list)
DFaug <- dplyr::bind_rows(DFaug_list)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...