寻找连续运行

时间:2017-01-18 22:28:55

标签: r

我有一个包含股票价格的数据框,如:

id     date        price
1     2/3/2016     4
1     2/4/2016     4.2
1     2/5/2016     3
2     2/4/2016     3
2     2/5/2016     4.1
2     2/6/2016     3
.     .            . 
.     .            . 
.     .            . 

然而,并非所有股票都涵盖同一时期,因为公司离开并加入交易所。我希望将我的数据子集化为连续的时间序列(忽略周末)。我面临着股票数量和时间长度之间的权衡(即时间序列越长,公司在整个系列中的数据就越少)。

我认为选择系列的最佳方法是它包含库存运行的开始日期和(可能不同的)库存运行的结束日期。任何其他时间段都不会最大化时间覆盖范围。最后,我期待一个包含可能的开始日期,结束日期和公司数量的数据框。然后我可以决定哪个时间范围最合适。

我希望这很清楚,如果需要澄清,请告诉我。

编辑:这应该有所帮助。这是一个粗略的数据框

date1 <- seq(as.Date("2006/1/1"), as.Date("2010/1/1"), "days")
date2 <- seq(as.Date("2006/6/12"), as.Date("2008/1/1"), "days")
date3 <- seq(as.Date("2009/10/11"), as.Date("2010/12/1"), "days")
date4 <- seq(as.Date("2002/1/1"), as.Date("2007/1/13"), "days")

row_to_drop1 <- !(weekdays(as.Date(date1)) %in% c('Saturday','Sunday'))
row_to_drop2 <- !(weekdays(as.Date(date2)) %in% c('Saturday','Sunday'))
row_to_drop3 <- !(weekdays(as.Date(date3)) %in% c('Saturday','Sunday'))
row_to_drop4 <- !(weekdays(as.Date(date4)) %in% c('Saturday','Sunday'))

date1 <- date1[row_to_drop1]
date2 <- date2[row_to_drop2]
date3 <- date3[row_to_drop3]
date4 <- date4[row_to_drop4]

mydf <- rbind.data.frame(data.frame(id = 1, date = date1),data.frame(id=2,date=date2),data.frame(id=2,date=date3),data.frame(id=3,date=date4))

我希望这个输出:

start       end         #ofids
1/1/2006    1/1/2010    1
6/12/2006   1/1/2010    2
10/11/2009  1/1/2010    3
1/1/2002    1/1/2010    3
1/1/2006    1/1/2008    3
6/12/2006   1/1/2008    1
10/11/2009  1/1/2008    2
1/1/2002    1/1/2008    3
1/1/2006    12/1/2010   1
6/12/2006   12/1/2010   3
10/11/2009  12/1/2010   2
1/1/2002    12/1/2010   2
1/1/2006    1/13/2007   2
6/12/2006   1/13/2007   1
10/11/2009  1/13/2007   1
1/1/2002    1/13/2007   1

#ofids刚刚组成,但希望它能够解决问题。由于开始日期不能大于结束日期,因此会删除某些行。

以下是运行(包含所有结束日期的开始日期的组合):

start       end
1/1/2006    1/1/2010
6/12/2006   1/1/2010
10/11/2009  1/1/2010
1/1/2002    1/1/2010
1/1/2006    1/1/2008
6/12/2006   1/1/2008
1/1/2002    1/1/2008
1/1/2006    12/1/2010
6/12/2006   12/1/2010
10/11/2009  12/1/2010
1/1/2002    12/1/2010
1/1/2006    1/13/2007
6/12/2006   1/13/2007
1/1/2002    1/13/2007

那应该是14x3(ids)= 42行。

1 个答案:

答案 0 :(得分:0)

以下是两种汇总数据的方法。首先,你需要在市场开放时制作一个向量;在这里,我只会使用工作日,但现实生活中的日历往往会更复杂。获得这样一个向量的一种简单方法是在quantmod之类的期间内为您知道在该交换中持续交易的索引提取数据,并提取日期。

library(dplyr)    # Use another grammar if you prefer

# Make a vector of dates the market is open
mkt_open <- seq(min(mydf$date), max(mydf$date), '1 day')
mkt_open <- mkt_open[!(weekdays(mkt_open) %in% c('Saturday','Sunday'))]

为每个id

运行

计算的一种方法是计算交易与否的每个id的运行。使用full_join在布尔变量中插入NA来判断公司是否正在交易允许使用data.table::rleid,它为每次运行返回一个ID(顺序整数)。 (您可以使用base::rle执行相同的操作,但这样做更有效。)分组后,有用地汇总数据非常简单。

mydf %>% mutate(trading = TRUE) %>%    # Add index column which will add NAs in join
    # Insert missing dates for each id
    full_join(crossing(id = unique(.$id), date = mkt_open)) %>% 
    mutate(trading = coalesce(trading, FALSE)) %>%    # Replace NAs with FALSE
    group_by(id) %>%
    arrange(date) %>%    # Sort by date before calculating runs
    group_by(run_id = data.table::rleid(trading), trading, add = TRUE) %>%    # Add ID to separate runs
    summarise(run_length = n(),    # Count rows per group
              start = min(date),
              end = max(date))

#> Source: local data frame [9 x 6]
#> Groups: id, run_id [?]
#> 
#>      id run_id trading run_length      start        end
#>   <dbl>  <int>   <lgl>      <int>     <date>     <date>
#> 1     1      1   FALSE       1044 2002-01-01 2005-12-30
#> 2     1      2    TRUE       1045 2006-01-02 2010-01-01
#> 3     1      3   FALSE        238 2010-01-04 2010-12-01
#> 4     2      1   FALSE       1159 2002-01-01 2006-06-09
#> 5     2      2    TRUE        407 2006-06-12 2008-01-01
#> 6     2      3   FALSE        463 2008-01-02 2009-10-09
#> 7     2      4    TRUE        298 2009-10-12 2010-12-01
#> 8     3      1    TRUE       1314 2002-01-01 2007-01-12
#> 9     3      2   FALSE       1013 2007-01-15 2010-12-01

如果您只关心公司正在进行的交易,请点击filter(trading) %>% select(-trading)

按交易公司数量运行

如果您更关心的是交易公司的数量而不是个人经营,您可以先汇总id

mydf %>% group_by(date) %>% 
    summarise(no_ids = n_distinct(id)) %>%    # Count ids per date
    full_join(data.frame(date = mkt_open)) %>%    # Add any dates w/o trading
    mutate(no_ids = coalesce(no_ids, 0L)) %>%    # Fill NAs for days w/o trading with 0
    arrange(date) %>%
    group_by(run_id = data.table::rleid(no_ids), no_ids) %>% 
    summarise(run_length = n(), 
              start = min(date), 
              stop = max(date))

#> Source: local data frame [7 x 5]
#> Groups: run_id [?]
#> 
#>   run_id no_ids run_length      start       stop
#>    <int>  <int>      <int>     <date>     <date>
#> 1      1      1       1044 2002-01-01 2005-12-30
#> 2      2      2        115 2006-01-02 2006-06-09
#> 3      3      3        155 2006-06-12 2007-01-12
#> 4      4      2        252 2007-01-15 2008-01-01
#> 5      5      1        463 2008-01-02 2009-10-09
#> 6      6      2         60 2009-10-12 2010-01-01
#> 7      7      1        238 2010-01-04 2010-12-01