Эффективное манипулирование и извлечение данных из нескольких матриц - средства и даты - PullRequest
0 голосов
/ 12 декабря 2018

У меня есть серия больших матриц, и я просто привыкаю к ​​навигации по ним в этом формате и работе с функциями.

У меня есть крошечные данные по ряду параметров, которые я смог сократить досреднесуточные значения - я хотел бы выровнять каждое среднее значение с последовательностью дат и оттуда извлечь среднесуточное значение для каждого года.

В единственном числе я сделал это следующим образом

A <- matrix(c(1:3285),nrow=3)
AA <- sapply(1:1095, function(x) mean(A [,x], na.rm = TRUE))
D <- seq(from = as.Date("2013-01-01"), to = as.Date("2015-12-31"), by= 1)
df <- cbind.data.frame(D,AA)

Что дает мне средства для каждого столбца, выровненные по дате 2013-2015

library(lubridate)
years <- year(as.Date(df$D, "%d-%b-%y"))
day <- yday(as.Date(df$D, "%d-%b-%y"))

 #to get the average of DOY over three years
  avg <- as.data.frame(tapply(df$AA,day, mean, na.rm=T)) #gives average value on day of year 
  #Average for specific DOY for each year
  av <- as.data.frame(tapply(df$AA,list(day,years), mean, na.rm=T)) #gets the DOY average per year

#bind to get yearly averages and overall average in a data frame format
DF <- cbind(av,avg)
head(DF)
colnames(DF)[4] <- "avg" #rename ts average column

Теперь скажите, что у меня есть несколько матриц (все одно измерение, только разные параметры), которые я хочу сделать для ...Есть ли эффективный способ пройти через это, так что я получаю вывод кадра данных (DF) для каждого AC?

 #extra matrices to play with:
 B <- matrix(c(3285:6570),nrow=3)
 C <- matrix(c(6570:9855),nrow=3)

До сих пор я получал некоторую начальную помощь в стеке:

#column means for each matrices
vapply(list(A, B, C), colMeans, numeric(1095))

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Вот решение tinyverse (т.е. без сторонних пакетов), которое оборачивает ваш процесс в функцию для получения матрицы в качестве входных данных и возврата фрейма данных в качестве выходных данных.Затем запустите lapply для списка матриц.

df_process <- function(mat) {
  # CREATE DF AND ADD NEW COLUMNS
  df <-  within(data.frame(D=seq(from = as.Date("2013-01-01"),
                                 to = as.Date("2015-12-31"), by= 1),
                           AA=sapply(1:1095, function(x) mean(mat[,x], na.rm=TRUE))), 
               {
                year <- format(as.Date(df$D, origin="1970-01-01"), "%Y")
                day <- format(as.Date(df$D, origin="1970-01-01"), "%d") 
               })

  # CREATE DF WITH TAPPLY CALLS, RENAME COLUMNS
  df <- setNames(data.frame(tapply(df$AA,list(day,years), mean, na.rm=T),
                            avg = c(tapply(df$AA, day, mean, na.rm=T))), 
                 c("2013", "2014", "2015", "avg"))
}

A <- matrix(c(1:3285),nrow=3)
B <- matrix(c(3286:6570),nrow=3)
C <- matrix(c(6571:9855),nrow=3)

# NAMED LIST OF DATA FRAMES
DF_list <- setNames(lapply(list(A, B, C), df_process), c("A", "B", "C"))

all.equal(DF, DF_list$A)
# [1] TRUE
identical(DF, DF_list$A)
# [1] TRUE

Вывод

lapply(DF_list, head)
# $A
#     2013   2014   2015    avg
# 01 501.5 1596.5 2691.5 1596.5
# 02 504.5 1599.5 2694.5 1599.5
# 03 507.5 1602.5 2697.5 1602.5
# 04 510.5 1605.5 2700.5 1605.5
# 05 513.5 1608.5 2703.5 1608.5
# 06 516.5 1611.5 2706.5 1611.5

# $B
#      2013   2014   2015    avg
# 01 3786.5 4881.5 5976.5 4881.5
# 02 3789.5 4884.5 5979.5 4884.5
# 03 3792.5 4887.5 5982.5 4887.5
# 04 3795.5 4890.5 5985.5 4890.5
# 05 3798.5 4893.5 5988.5 4893.5
# 06 3801.5 4896.5 5991.5 4896.5

# $C
#      2013   2014   2015    avg
# 01 7071.5 8166.5 9261.5 8166.5
# 02 7074.5 8169.5 9264.5 8169.5
# 03 7077.5 8172.5 9267.5 8172.5
# 04 7080.5 8175.5 9270.5 8175.5
# 05 7083.5 8178.5 9273.5 8178.5
# 06 7086.5 8181.5 9276.5 8181.5
0 голосов
/ 13 декабря 2018

Вот решение tidyverse.Пусть

dates <- seq(from = as.Date("2013-01-01"), to = as.Date("2015-12-31"), by = 1)
A <- data.frame(matrix(c(1:3285), ncol = 3, byrow = TRUE))

, так как я понимаю, что даты одинаковы для всех матриц.Кроме того, я сделал A длинным, а не широким, это лучше при работе с tidyverse.Тогда, возможно, вы бы предпочли вывод в виде

A %>% group_by(year = year(dates), day = yday(dates)) %>% 
  summarise(dayYearAvg = mean(c(X1, X2, X3))) %>%
  group_by(day) %>% mutate(dayAvg = mean(dayYearAvg))
# A tibble: 1,095 x 4
# Groups:   day [365]
#     year   day dayYearAvg dayAvg
#    <dbl> <dbl>      <dbl>  <dbl>
#  1  2013     1          2   1097
#  2  2013     2          5   1100
#  3  2013     3          8   1103
#  ...

Если нет, мы получим то же, что и в вашем примере с

A %>% group_by(year = year(dates), day = yday(dates)) %>% 
  summarise(dayYearAvg = mean(c(X1, X2, X3))) %>%
  group_by(day) %>% mutate(dayAvg = mean(dayYearAvg)) %>%
  spread(year, dayYearAvg) %>% ungroup %>% select(-day)
# A tibble: 365 x 4
#    dayAvg `2013` `2014` `2015`
#     <dbl>  <dbl>  <dbl>  <dbl>
#  1   1097      2   1097   2192
#  2   1100      5   1100   2195
#  3   1103      8   1103   2198
#  4   1106     11   1106   2201
#  ...

Теперь позвольте также

B <- data.frame(matrix(c(3285:6569), ncol = 3, byrow = TRUE))
C <- data.frame(matrix(c(6570:9854), ncol = 3, byrow = TRUE))
l <- list(A, B, C)

Это дает

map(l, . %>% group_by(year = year(dates), day = yday(dates)) %>% 
      summarise(dayYearAvg = mean(c(X1, X2, X3))) %>%
      group_by(day) %>% mutate(dayAvg = mean(dayYearAvg)) %>%
      spread(year, dayYearAvg) %>% ungroup %>% select(-day))
# [[1]]
# A tibble: 365 x 4
#    dayAvg `2013` `2014` `2015`
#     <dbl>  <dbl>  <dbl>  <dbl>
#  1   1097      2   1097   2192
#  2   1100      5   1100   2195
#  ...
# [[2]]
# A tibble: 365 x 4
#    dayAvg `2013` `2014` `2015`
#     <dbl>  <dbl>  <dbl>  <dbl>
#  1   4381   3286   4381   5476
#  2   4384   3289   4384   5479
#  ...
# [[3]]
# A tibble: 365 x 4
#    dayAvg `2013` `2014` `2015`
#     <dbl>  <dbl>  <dbl>  <dbl>
#  1   7666   6571   7666   8761
#  2   7669   6574   7669   8764
#  ...
...