Применение функции с элементами времени - PullRequest
0 голосов
/ 14 мая 2018

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

1) подсчитайте, сколько часов есть на каждый месяц контракта, умножьте это на стоимость и количество 2) и получите данные, возвращенные во фрейме данных на группу.

Данные:

df <- structure(list(Fromdate = structure(c(1388530800, 1388530800, 
1388530800, 1388530800, 1388530800, 1388530800, 1388530800, 1388530800, 
1388530800, 1420066800, 1388530800, 1388530800, 1388530800, 1388530800, 
1420066800), class = c("POSIXct", "POSIXt"), tzone = "CET"), 
    Todate = structure(c(1419980400, 1419980400, 1419980400, 
    1419980400, 1419980400, 1419980400, 1419980400, 1419980400, 
    1419980400, 1451516400, 1419980400, 1419980400, 1419980400, 
    1419980400, 1451516400), class = c("POSIXct", "POSIXt"), tzone = "CET"), 
    Cost = c(1.58, 1.58, 1.58, 1.58, 1.58, 1.58, 1.58, 1.58, 
    1.58, 1.58, 1.58, 1.58, 1.58, 1.58, 1.58), Quantity = c(0.112311303786473, 
    0.0205773161568493, 0.0493657482020549, 0.0437536029132876, 
    0.0278005475976713, 0.0295483138287671, 0.066499635323105, 
    0.066499635323105, 0.733925139981052, 0.733925139981051, 
    0.1067060088379, 0.436262087700001, 0.0667432627739724, 0.0925740588127852, 
    0.0925740588127855), Group = structure(c(1L, 1L, 1L, 1L, 
    1L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L), .Label = c("A", 
    "B", "C"), class = "factor")), class = "data.frame", row.names = c(NA, 
-15L))

1) Вычисление, которое я хочу сделать, просто применимо к этому:

table(
  format(seq.POSIXt(df$Fromdate[1], to = df$Todate[1], by = "hour"), "%Y-%m")
) *  df$Cost[1] * df$Quantity[1]


2014-01  2014-02  2014-03  2014-04  2014-05  2014-06  2014-07  2014-08  2014-09  2014-10  2014-11  2014-12 
132.0242 119.2476 131.8467 127.7653 132.0242 127.7653 132.0242 132.0242 127.7653 132.2016 127.7653 127.9428 

Но, для моей жизни,Я не могу понять это и применить, lapply или любые purrr-функции.

2) В конце я также хочу сгруппировать его по группам, поэтому конечный результат должен быть списком или фреймом данных с отдельными месяцами и суммарными затратами на группу.

Примерно так:

df %>% group_by(Group, month_year) %>% 
  summarise_each(table(
    format(
      seq.POSIXt("FromDate", "Todate", by = "hour")
      , "%Y-%m")  # this is month_year
    ) * Cost * Quantity )

Или проще для понимания - конечный результат должен быть просто: (цифры не верны)

  2014-01 2014-02 .... 2015-12
A   600     900     ...  1100
B   650     600     ...  1870
C   400     700     ...  990

1 Ответ

0 голосов
/ 14 мая 2018

Извините, @NoThanks, но эта штука превратилась в кроличью нору, которую у меня нет времени, чтобы полностью изучить ее, поэтому это только частично ответит на ваш вопрос.

Сначала мы разбиваем данные в два этапа(Шаг один для разных лет, обозначенный df$Fromdate, шаг второй для df$Group):

part1 <- split(df, df$Fromdate)
part2 <- lapply(part1, function(x) split(x, x$Group))

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

part3 <- lapply(part2, function(a) lapply(a, function(b) Map(function(w,x,y,z) table(format(seq.POSIXt(w, to = x, by = "hour"), "%Y-%m")
) *  y * z, b$Fromdate, b$Todate, b$Cost, b$Quantity)))

Теперь мы rbind группы в годах.

part4 <- lapply(part3, function(x) lapply(x, function(y) do.call(rbind, y)))

Теперь нам нужно удалить возможные NULL объекты из вложенного списка.Мы используем небольшую удобную функцию, которую я когда-то нашел в интернете:

rmNullObs <- function(x) {
  is.NullOb <- function(x) is.null(x) | all(sapply(x, is.null))
   x <- Filter(Negate(is.NullOb), x)
   lapply(x, function(x) if (is.list(x)) rmNullObs(x) else x)
}

part4 <- rmNullObs(part4)

А теперь мы rbind лет:

part5 <- lapply(part4, function(x) do.call(rbind, lapply(x, function(y) colSums(y))))

оставив нас с этим:

> part5
$`2014-01-01`
    2014-01  2014-02   2014-03   2014-04   2014-05   2014-06   2014-07   2014-08   2014-09   2014-10   2014-11   2014-12
A  298.3570 269.4837  297.9560  288.7326  298.3570  288.7326  298.3570  298.3570  288.7326  298.7580  288.7326  289.1336
B 1053.8216 951.8389 1052.4052 1019.8274 1053.8216 1019.8274 1053.8216 1053.8216 1019.8274 1055.2380 1019.8274 1021.2438
C  825.5506 745.6586  824.4409  798.9199  825.5506  798.9199  825.5506  825.5506  798.9199  826.6602  798.9199  800.0295

$`2015-01-01`
   2015-01   2015-02  2015-03  2015-04  2015-05  2015-06  2015-07  2015-08  2015-09  2015-10  2015-11  2015-12
B 862.7437 779.25236 861.5841 834.9132 862.7437 834.9132 862.7437 862.7437 834.9132 863.9033 834.9132 836.0728
C 108.8227  98.29143 108.6764 105.3122 108.8227 105.3122 108.8227 108.8227 105.3122 108.9689 105.3122 105.4585

Объединить их сложно из-за отсутствия общих столбцов и отсутствующих групп.Возможное решение, которое я пробовал, заключалось в ручном добавлении NA заполненных строк для отсутствующих групп через цикл for, но, поскольку это сильно зависит от ваших реальных данных, вам придется выяснить это самостоятельно или просто работать сэти сравнения из года в год.

Надеюсь, это помогло.

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