【问题标题】:Create a vector in R by summing rows based on multiple criteria通过基于多个条件对行求和来在 R 中创建一个向量
【发布时间】:2016-04-22 10:00:05
【问题描述】:

我有当前以 15 分钟为间隔的财务数据,但我想在进行其余分析之前将间隔从 15 分钟转换为 30 分钟。因此,我想将两个相邻 15 分钟间隔的交易量相加,并取第二个 15 分钟子间隔的收盘价(即 30 分钟时段的结束)。

我在下面展示了一个使用 sapply 函数的数据 (df) 和所需输出 (df.30min) 的示例。这适用于下面的示例,但考虑到我正在分析 10 年的每日数据,每天有 50 家公司和 27 个间隔,处理时间过长,即使是一年的数据也是如此。如果我尝试 for 循环,我也会遇到类似的问题。

我是 R 新手,所以我希望有一个使用其中一个内置函数的相当简单的解决方案。

在我的实际数据集中,有 27 x 15 分钟的间隔 (10:00-16:45)。我希望我的最终“30 分钟”数据集在 13:30-13:45 之间有一个 15 分钟的间隔。此外,可能还有其他异常情况,例如证券交易所开盘较晚/提早收盘或股票在一天中途暂停交易。 (我已经设法使用具有匹配功能的查找表将数据中的时间映射到正确的间隔。)鉴于我的数据结构不完美,我正在寻求一个不依赖于完整集合且完全偶数的解决方案15分钟间隔。在 Excel 中,我会使用 sumifs 函数。

set.seed(1)
df <- data.frame(
  Company = rep(c("Co A", "Co B", "Co C"), each = 8),
  Date = as.Date(rep(c("2005-01-01", "2005-01-02"), times = 3, each = 4)),
  Time = as.factor(c("10:00:00", "10:15:00", "10:30:00", "10:45:00")),
  Interval = as.factor(c(1,1,2,2)),
  Interval.End = as.factor(c(0,1)),
  Close = abs(round(rnorm(24),1))*10+100,
  Volume = abs(round(rnorm(24),1))*10)

> df
   Company       Date     Time Interval Interval.End Close Volume
1     Co A 2005-01-01 10:00:00        1            0   106      6
2     Co A 2005-01-01 10:15:00        1            1   102      1
3     Co A 2005-01-01 10:30:00        2            0   108      2
4     Co A 2005-01-01 10:45:00        2            1   116     15
5     Co A 2005-01-02 10:00:00        1            0   103      5
6     Co A 2005-01-02 10:15:00        1            1   108      4
7     Co A 2005-01-02 10:30:00        2            0   105     14
8     Co A 2005-01-02 10:45:00        2            1   107      1
9     Co B 2005-01-01 10:00:00        1            0   106      4
10    Co B 2005-01-01 10:15:00        1            1   103      1
11    Co B 2005-01-01 10:30:00        2            0   115     14
12    Co B 2005-01-01 10:45:00        2            1   104      4
13    Co B 2005-01-02 10:00:00        1            0   106      4
14    Co B 2005-01-02 10:15:00        1            1   122      1
15    Co B 2005-01-02 10:30:00        2            0   111     11
16    Co B 2005-01-02 10:45:00        2            1   100      8
17    Co C 2005-01-01 10:00:00        1            0   100      2
18    Co C 2005-01-01 10:15:00        1            1   109      3
19    Co C 2005-01-01 10:30:00        2            0   108      7
20    Co C 2005-01-01 10:45:00        2            1   106      6
21    Co C 2005-01-02 10:00:00        1            0   109      7
22    Co C 2005-01-02 10:15:00        1            1   108      7
23    Co C 2005-01-02 10:30:00        2            0   101      4
24    Co C 2005-01-02 10:45:00        2            1   120      8

df.30min <- df[-which(df$Interval.End == 0),]

df.30min$Volume <-sapply(seq_len(nrow(df.30min)),
            function(i) sum(df$Volume[df$Company == df.30min$Company[i] &
                                        df$Date == df.30min$Date[i] &
                                        df$Interval == df.30min$Interval[i]]))

> df.30min
   Company       Date     Time Interval Interval.End Close Volume
2     Co A 2005-01-01 10:15:00        1            1   102      7
4     Co A 2005-01-01 10:45:00        2            1   116     17
6     Co A 2005-01-02 10:15:00        1            1   108      9
8     Co A 2005-01-02 10:45:00        2            1   107     15
10    Co B 2005-01-01 10:15:00        1            1   103      5
12    Co B 2005-01-01 10:45:00        2            1   104     18
14    Co B 2005-01-02 10:15:00        1            1   122      5
16    Co B 2005-01-02 10:45:00        2            1   100     19
18    Co C 2005-01-01 10:15:00        1            1   109      5
20    Co C 2005-01-01 10:45:00        2            1   106     13
22    Co C 2005-01-02 10:15:00        1            1   108     14
24    Co C 2005-01-02 10:45:00        2            1   120     12

【问题讨论】:

    标签: r criteria sumifs


    【解决方案1】:

    使用库dplyr,你可以尝试这样的事情:

    library(dplyr)
    df %>% arrange(Company, Date, Time, Interval, Interval.End) %>% group_by(Company, Date, Interval) %>% summarise(Time = Time[2], Interval.End = Interval.End[2], Close = Close[2], Volume = sum(Volume))
    Source: local data frame [12 x 7]
    Groups: Company, Date [?]
    
       Company       Date Interval     Time Interval.End Close Volume
        (fctr)     (date)   (fctr)   (fctr)       (fctr) (dbl)  (dbl)
    1     Co A 2005-01-01        1 10:15:00            1   102      7
    2     Co A 2005-01-01        2 10:45:00            1   116     17
    3     Co A 2005-01-02        1 10:15:00            1   108      9
    4     Co A 2005-01-02        2 10:45:00            1   107     15
    5     Co B 2005-01-01        1 10:15:00            1   103      5
    6     Co B 2005-01-01        2 10:45:00            1   104     18
    7     Co B 2005-01-02        1 10:15:00            1   122      5
    8     Co B 2005-01-02        2 10:45:00            1   100     19
    9     Co C 2005-01-01        1 10:15:00            1   109      5
    10    Co C 2005-01-01        2 10:45:00            1   106     13
    11    Co C 2005-01-02        1 10:15:00            1   108     14
    12    Co C 2005-01-02        2 10:45:00            1   120     12
    

    如果您的数据框已经安排妥当,您可以去掉上面的arrange 部分。

    注意:我假设总是有两个区间 (0, 1),因此使用硬编码值 2。如果不是这种情况,您可以使用适当的子集。

    【讨论】:

    • 这似乎在我的实际数据集上运行良好,而且速度更快。然而,间隔并不总是成对的。交易所每天 16:45 关闭,所以我在 13:30-13:45 分配了 15 分钟的间隔。此外,一家公司可能在某一天暂停交易,交易所可能会延迟开市/提早收市等。我没有在上面的示例代码中显示间隔分配,但它基于一个查找表,其中 df$实际数据集中的时间在 10:00 到 16:45 之间有 15 分钟的间隔。是否可以将其合并到代码的汇总部分以避免硬编码 2?
    【解决方案2】:

    我们可以使用data.table 来做到这一点

    library(data.table)
    setDT(df)[order(Company, Date, Time, Interval),
         list(Time=Time[2L],  Interval.End = Interval.End[2L],
              Close = Close[2L], Volume = sum(Volume)),
                   by = .(Company, Date, Interval)]
    #     Company       Date Interval     Time Interval.End Close Volume
    # 1:    Co A 2005-01-01        1 10:15:00            1   102      7
    # 2:    Co A 2005-01-01        2 10:45:00            1   116     17
    # 3:    Co A 2005-01-02        1 10:15:00            1   108      9
    # 4:    Co A 2005-01-02        2 10:45:00            1   107     15
    # 5:    Co B 2005-01-01        1 10:15:00            1   103      5
    # 6:    Co B 2005-01-01        2 10:45:00            1   104     18
    # 7:    Co B 2005-01-02        1 10:15:00            1   122      5
    # 8:    Co B 2005-01-02        2 10:45:00            1   100     19
    # 9:    Co C 2005-01-01        1 10:15:00            1   109      5
    #10:    Co C 2005-01-01        2 10:45:00            1   106     13
    #11:    Co C 2005-01-02        1 10:15:00            1   108     14
    #12:    Co C 2005-01-02        2 10:45:00            1   120     12
    

    【讨论】:

      猜你喜欢
      • 2019-04-20
      • 2015-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多