将移动年份值重新分配到实际月份

时间:2017-02-17 14:27:44

标签: r

我有data.frame,其中包含3个观察值的最近12个月值。有一个Date变量与month.m0(最新的)相对应,然后值每次减去一个月的时间倒退:

date <- c("2017-01-01", "2016-12-01", "2016-10-01")
month.m0 <- c(1, 2, 3)
month.m1 <- c(4, 5, 6)
month.m2 <- c(7, 8, 9)
month.m3 <- c(10, 11, 12)
month.m4 <- c(13, 14, 15)
month.m5 <- c(16, 17, 18)
month.m6 <- c(19, 20, 21)
month.m7 <- c(22, 23, 24)
month.m8 <- c(25, 26, 27)
month.m9 <- c(28, 29, 30)
month.m10 <- c(31, 32, 33)
month.m11 <- c(34, 35, 36)

df <- data.frame(date, month.m0, month.m1, month.m2, month.m3, month.m4, month.m5, month.m6, month.m7, month.m8, month.m9, month.m10, month.m11)

输入将是:

        date month.m0 month.m1 month.m2 month.m3 month.m4 month.m5 month.m6 month.m7 month.m8 month.m9 month.m10 month.m11
1 2017-01-01        1        4        7       10       13       16       19       22       25       28        31        34
2 2016-12-01        2        5        8       11       14       17       20       23       26       29        32        35
3 2016-10-01        3        6        9       12       15       18       21       24       27       30        33        36

这里的问题是我不知道每个观察的真实月份,因为数字是有序的并且取决于日期变量。

初始值(month.m0)对应于第1行到1月份,因为日期是1月(无论是白天还是年份)。对于第二行,日期表示 month.m0 对应于12月,第三行对应于10月。然后, month.m1 ((月(日期) - 月(1))值,month.m2对应(月(日期) - 几个月(2))等等,从最初的值回溯到时间

编辑输出:

我试图将每个值分配给实际月份,因此输出将为:

        date Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1 2017-01-01   1  34  31  28  25  22  19  16  13  10   7   4
2 2016-12-01  35  32  29  26  23  20  17  14  11   8   5   2
3 2016-10-01  30  27  24  21  18  15  12   9   6   3  36  33

为每次观察分配第一个月很容易,但是当它倒退时会很复杂。有什么想法吗?

EDITED SOLUTION:

最后,同性恋者给出了关键:我接受了@AntoniosK的答案并修改了一些操作员以获得解决方案:

df %>%
  gather(month_num,value,-date) %>%                                        # reshape datset
  mutate(month_num = as.numeric(gsub("month.m","",month_num)),             # keep only the number (as your step)
         date = ymd(date),                                                 # transform date to date object
         month_actual = month(date),                                       # keep the number of the actual month (baseline)
         month_now = month_actual - month_num,                             # create the current month (baseline + step)
         month_now_upd = ifelse(month_now < 1, month_now+12, month_now),  # update month number (for numbers < 1)
         month_now_upd_name = month(month_now_upd, label=T)) %>%           # get name of the month
  select(date, month_now_upd_name, value) %>%                              # keep useful columns
  spread(month_now_upd_name, value) %>%                                    # reshape again
  arrange(desc(date)) 

2 个答案:

答案 0 :(得分:0)

假设df是您提供的数据框......

library(dplyr)
library(tidyr)
library(lubridate)

df %>%
  gather(month_num,value,-date) %>%                                        # reshape datset
  mutate(month_num = as.numeric(gsub("month.m","",month_num)),             # keep only the number (as your step)
         date = ymd(date),                                                 # transform date to date object
         month_actual = month(date),                                       # keep the number of the actual month (baseline)
         month_now = month_actual + month_num,                             # create the current month (baseline + step)
         month_now_upd = ifelse(month_now > 12, month_now-12, month_now),  # update month number (for numbers > 12)
         month_now_upd_name = month(month_now_upd, label=T)) %>%           # get name of the month
  select(date, month_now_upd_name, value) %>%                              # keep useful columns
  spread(month_now_upd_name, value) %>%                                    # reshape again
  arrange(desc(date))                                                      # start from recent month

#         date Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
# 1 2017-01-01   1   4   7  10  13  16  19  22  25  28  31  34
# 2 2016-12-01   5   8  11  14  17  20  23  26  29  32  35   2
# 3 2016-10-01  12  15  18  21  24  27  30  33  36   3   6   9

请注意,我创建了最终不需要的各种(有用的)变量,但它们将帮助您逐步运行链式命令时理解该过程。 如果需要,可以通过组合mutate中的一些命令来缩短上述代码。

答案 1 :(得分:0)

你的解释对我来说不是很清楚,所以我的输出并不完全是你的。但这就是我要这样做的方式:

Function IsMember(mT as myType, rngIN as Range) As Boolean
   Dim i As Long
   IsMember = False
   For i = 1 To rngIN.Rows.Count
      IsMember = rngIN.Cells(i, 1) = mT.slot1 And rngIN.Cells(i, 2) = mT.slot2
      If (IsMember) Then
         Exit For
      End If
   Next i
End Function