我有一个包含股票价格的数据框,如:
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行。
答案 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