Эффективный способ построить сложный информационный фрейм построчно в R - PullRequest
3 голосов
/ 16 апреля 2019

:) Привет всем

да, я знаю, что уже есть несколько советов и приемов, как эффективно строить ряд за строкой, но мой цикл for все еще медленный. Может быть, для одного из вас очевидно, как это ускорить / почему это так медленно.

Как вы можете видеть, я уже преобразовал его в список, следуя инструкциям: Построение кадра данных R строка за строкой , но это не делает его намного быстрее, чем rbind.

index = 1

for (i in 1:nrow(predictionDf)) {

  startDate = predictionDf$ApropYMD[i]
  amountPerMonth = (predictionDf$PredictionExp[i]/12)
  amountPerMonthMax = (predictionDf$PredictionMax[i]/12)

  print(i)

  for (j in 1:12) {

    plotDf[index, ] = list(ApropYMD=startDate, AmountExp = amountPerMonth, AmountMax = amountPerMonthMax)
    month(startDate) <- month(startDate) + 1
    index = index + 1
  }


}

Я тоже попробовал, это немного быстрее

plotDf = data.frame("ApropYMD" =  c(seq(firstDayNextMonth, highestDate, by="months")))
plotDf$AmountExp = 0
plotDf$AmountMax = 0

for (i in 1:nrow(tmpPredictionDf)) { 

  startDate = tmpPredictionDf$ApropYMD[i]
  amountPerMonth = (tmpPredictionDf$PredictionExp[i]/12)
  amountPerMonthMax = (tmpPredictionDf$PredictionMax[i]/12)

  print(i)

  for (j in 1:12) {

    plotDf$AmountExp[which(plotDf$ApropYMD == startDate)] = plotDf$AmountExp[which(plotDf$ApropYMD == startDate)] + amountPerMonth
    plotDf$AmountMax[which(plotDf$ApropYMD == startDate)] = plotDf$AmountMax[which(plotDf$ApropYMD == startDate)] + amountPerMonthMax
    month(startDate) <- month(startDate) + 1

  }

Я хочу распределить количество на одну дату в течение следующих 12 месяцев для каждой из ~ 5,500 строк -> 5,500 * 12 = 66 000 вставок строк

Input       
ApropYMD    AmountExp   AmountMax
2019-01-01  6000    12000

Output      
ApropYMD    AmountExp   AmountMax
2019-01-01  500 1000
2019-01-02  500 1000
2019-01-03  500 1000
2019-01-04  500 1000
2019-01-05  500 1000
2019-01-06  500 1000
2019-01-07  500 1000
2019-01-08  500 1000
2019-01-09  500 1000
2019-01-10  500 1000
2019-01-11  500 1000
2019-01-12  500 1000

Ответы [ 2 ]

2 голосов
/ 16 апреля 2019

Заполнение цикла данных в цикле не рекомендуется, и обычно оно выполняется медленно.Мы можем использовать уже существующие функции, чтобы сделать это.Например, один из способов сделать это с tidyr::complete.Предполагая, что у вас есть ApropYMD класса «Дата», мы можем расширить каждую строку до 12 строк, сгруппировав каждую строку и создав последовательность дат для каждого месяца, а затем разделив значение first на AmountExp и AmountMax на 12так что он равномерно распределен.

library(dplyr)
library(tidyr)

df %>%
  group_by(group = row_number()) %>%
  complete(ApropYMD = seq(ApropYMD, length.out = 12, by = "month"), 
           fill = list(AmountExp = 0, AmountMax = 0)) %>%
  mutate(AmountExp = first(AmountExp)/12, 
         AmountMax = first(AmountMax)/12) %>% 
  ungroup() %>%
  select(-group)


# A tibble: 24 x 3
#   ApropYMD   AmountExp AmountMax
#   <date>         <dbl>     <dbl>
# 1 2019-01-01       500      1000
# 2 2019-02-01       500      1000
# 3 2019-03-01       500      1000
# 4 2019-04-01       500      1000
# 5 2019-05-01       500      1000
# 6 2019-06-01       500      1000
# 7 2019-07-01       500      1000
# 8 2019-08-01       500      1000
# 9 2019-09-01       500      1000
#10 2019-10-01       500      1000
# … with 14 more rows

data

Добавлена ​​еще одна дополнительная строка для проверки решения

df <- read.table(text = "ApropYMD    AmountExp   AmountMax
2019-01-01  6000    12000
2018-01-01  12000    24000", header = T)
df$ApropYMD <- as.Date(df$ApropYMD)
1 голос
/ 16 апреля 2019

Мы можем сделать это без какой-либо группировки.Выполните деление в начале, а затем используйте map, чтобы развернуть 'ApropYMD' и unnest

library(tidyverse)
df %>% 
   mutate_at(2:3, list(~ ./ 12)) %>%
   mutate(ApropYMD = map(ApropYMD, seq, length.out = 12, by = "month")) %>%
   unnest
#   AmountExp AmountMax   ApropYMD
#1        500      1000 2019-01-01
#2        500      1000 2019-02-01
#3        500      1000 2019-03-01
#4        500      1000 2019-04-01
#5        500      1000 2019-05-01
#6        500      1000 2019-06-01
#7        500      1000 2019-07-01
#8        500      1000 2019-08-01
#9        500      1000 2019-09-01
#10       500      1000 2019-10-01
#11       500      1000 2019-11-01
#12       500      1000 2019-12-01
#13      1000      2000 2018-01-01
#14      1000      2000 2018-02-01
#15      1000      2000 2018-03-01
#16      1000      2000 2018-04-01
#17      1000      2000 2018-05-01
#18      1000      2000 2018-06-01
#19      1000      2000 2018-07-01
#20      1000      2000 2018-08-01
#21      1000      2000 2018-09-01
#22      1000      2000 2018-10-01
#23      1000      2000 2018-11-01
#24      1000      2000 2018-12-01

data

df <- structure(list(ApropYMD = structure(c(17897, 17532), class = "Date"), 
AmountExp = c(6000L, 12000L), AmountMax = c(12000L, 24000L
)), row.names = c(NA, -2L), class = "data.frame")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...