合并两个具有不规则时间戳列的数据帧
Merging two dataframes with irregular timestamp columns
我有一个与股票相关的数据样本,其中的价格 date/time 在几秒钟内以不规则的随机间隔标记,称为 ESH5
和 ESM5
我想生成另一个 full data.frame,其中一个 date/time 列以秒为单位递增时间,并填写来自ESH5
、ESM5
。除非 ESH5
或 ESM5
中存在匹配时间的值,否则任何值都将成为 'latest price',它将延续到下一个时间间隔
例如,ESH5
Date Price Type
22/10/2015 9:00:00 50.10 Bid
22/10/2015 9:00:02 50.12 Ask
22/10/2015 9:00:06 50.10 Trade
ESM5
Date Price Type
22/10/2015 9:00:01 50.09 Bid
22/10/2015 9:00:02 50.11 Ask
22/10/2015 9:00:04 50.09 Trade
我希望生成一个完整的 data.frame 喜欢
Date ESH5.Bid ESH5.Ask ESH5.Trade ESM5.Bid ESM5.Ask ESM5.Trade
22/10/2015 9:00:00 50.10 NA NA NA NA NA
22/10/2015 9:00:01 50.10 NA NA 50.09 NA NA
22/10/2015 9:00:02 50.10 50.12 NA 50.09 50.11 NA
22/10/2015 9:00:03 50.10 50.12 NA 50.09 50.11 NA
22/10/2015 9:00:04
22/10/2015 9:00:05
22/10/2015 9:00:06
目前,我正在使用 for 循环和 if-else 语句生成 table。我使用常规时间戳增量预生成 NA
空数据帧,最新更新 bid
、ask
、trade
,然后 运行 同时进行条件检查填写table。
我当前的代码有效,但是循环需要相当长的时间来处理(10 分钟)。 R 中是否有任何内置函数可用于此搜索、替换和继承类似功能?
如果这有点难以理解,我们深表歉意。谢谢。
我认为你想要做的事情需要几个步骤:
首先,使用 seq
创建日期列,如 @akrun
所示
其次重建数据结构。这可以通过多种方式完成,但我认为 reshape2
包中的 dcast
函数是最好的:
ESH5c <- dcast(ESH5, Date ~ Type, value.var='Price')
ESM5c <- dcast(ESM5, Date ~ Type, value.var='Price')
最后一步是 merge
这些新数据与您的日期向量。
将两个数据集中的 'Date' 列从 'character' class 转换为 'POSIXct'。
ESH5$Date <- as.POSIXct(ESH5$Date, format='%d/%m/%Y %H:%M:%S')
ESM5$Date <- as.POSIXct(ESM5$Date, format='%d/%m/%Y %H:%M:%S')
通过连接这些数据集的 'Date' 列得到 'min' 和 'max' 值。
MinD <- min(c(ESH5$Date, ESM5$Date))
MaxD <- max(c(ESH5$Date, ESM5$Date))
根据 'MinD' 和 'MaxD' 值创建日期时间序列作为新数据集
d1 <- data.frame(Date=seq(MinD, MaxD, by='sec'))
merge
所有数据集,方法是将它们放在 'list' 中并使用 Reduce
d2 <- Reduce(function(...) merge(..., by='Date', all=TRUE),
list(d1, ESH5, ESM5))
将 'd2' 数据集从 'wide' 重塑为 'long'
dLong <- reshape(d2, idvar='Date', varying=2:5, sep=".", direction='long')
dLong$time <- factor(dLong$time, labels=c('ESH5', 'ESM5'))
row.names(dLong) <- NULL
使用 dcast
将 'long' 格式更改为 'wide'
library(reshape2)
res <- dcast(dLong, Date~time+Type, value.var='Price')
删除多余的 NA 列
res1 <- res[!grepl('NA', names(res))]
使用 zoo
中的 na.locf
用之前的非 NA 值填充 NA 值
library(zoo)
res1[-1] <- lapply(res1[-1], na.locf, na.rm=FALSE)
res1
# Date ESH5_Ask ESH5_Bid ESH5_Trade ESM5_Ask ESM5_Bid ESM5_Trade
#1 2015-10-22 09:00:00 NA 50.1 NA NA NA NA
#2 2015-10-22 09:00:01 NA 50.1 NA NA 50.09 NA
#3 2015-10-22 09:00:02 50.12 50.1 NA 50.11 50.09 NA
#4 2015-10-22 09:00:03 50.12 50.1 NA 50.11 50.09 NA
#5 2015-10-22 09:00:04 50.12 50.1 NA 50.11 50.09 50.09
#6 2015-10-22 09:00:05 50.12 50.1 NA 50.11 50.09 50.09
#7 2015-10-22 09:00:06 50.12 50.1 50.1 50.11 50.09 50.09
或者使用dplyr/tidyr
,我们可以使用spread
来改变每个数据集的格式,full_join
,它们与'd1'一起改变'NA' 每列中的值与使用 na.locf
和 mutate_each
的 'non-NA' 先前值。使用 paste
(如果需要)更改列名称。
library(dplyr)
library(tidyr)
library(zoo)
res2 <- full_join(spread(ESH5, Type, Price),
spread(ESM5, Type, Price), by='Date') %>%
full_join(d1, ., by='Date') %>%
mutate_each(funs(na.locf(., na.rm=FALSE)), -Date)
names(res2)[-1] <- c(paste('ESH5', sort(ESH5$Type),sep="_"),
paste('ESM5', sort(ESM5$Type), sep="_"))
res2
# Date ESH5_Ask ESH5_Bid ESH5_Trade ESM5_Ask ESM5_Bid ESM5_Trade
#1 2015-10-22 09:00:00 NA 50.1 NA NA NA NA
#2 2015-10-22 09:00:01 NA 50.1 NA NA 50.09 NA
#3 2015-10-22 09:00:02 50.12 50.1 NA 50.11 50.09 NA
#4 2015-10-22 09:00:03 50.12 50.1 NA 50.11 50.09 NA
#5 2015-10-22 09:00:04 50.12 50.1 NA 50.11 50.09 50.09
#6 2015-10-22 09:00:05 50.12 50.1 NA 50.11 50.09 50.09
#7 2015-10-22 09:00:06 50.12 50.1 50.1 50.11 50.09 50.09
我有一个与股票相关的数据样本,其中的价格 date/time 在几秒钟内以不规则的随机间隔标记,称为 ESH5
和 ESM5
我想生成另一个 full data.frame,其中一个 date/time 列以秒为单位递增时间,并填写来自ESH5
、ESM5
。除非 ESH5
或 ESM5
例如,ESH5
Date Price Type
22/10/2015 9:00:00 50.10 Bid
22/10/2015 9:00:02 50.12 Ask
22/10/2015 9:00:06 50.10 Trade
ESM5
Date Price Type
22/10/2015 9:00:01 50.09 Bid
22/10/2015 9:00:02 50.11 Ask
22/10/2015 9:00:04 50.09 Trade
我希望生成一个完整的 data.frame 喜欢
Date ESH5.Bid ESH5.Ask ESH5.Trade ESM5.Bid ESM5.Ask ESM5.Trade
22/10/2015 9:00:00 50.10 NA NA NA NA NA
22/10/2015 9:00:01 50.10 NA NA 50.09 NA NA
22/10/2015 9:00:02 50.10 50.12 NA 50.09 50.11 NA
22/10/2015 9:00:03 50.10 50.12 NA 50.09 50.11 NA
22/10/2015 9:00:04
22/10/2015 9:00:05
22/10/2015 9:00:06
目前,我正在使用 for 循环和 if-else 语句生成 table。我使用常规时间戳增量预生成 NA
空数据帧,最新更新 bid
、ask
、trade
,然后 运行 同时进行条件检查填写table。
我当前的代码有效,但是循环需要相当长的时间来处理(10 分钟)。 R 中是否有任何内置函数可用于此搜索、替换和继承类似功能?
如果这有点难以理解,我们深表歉意。谢谢。
我认为你想要做的事情需要几个步骤:
首先,使用 seq
创建日期列,如 @akrun
其次重建数据结构。这可以通过多种方式完成,但我认为 reshape2
包中的 dcast
函数是最好的:
ESH5c <- dcast(ESH5, Date ~ Type, value.var='Price')
ESM5c <- dcast(ESM5, Date ~ Type, value.var='Price')
最后一步是 merge
这些新数据与您的日期向量。
将两个数据集中的 'Date' 列从 'character' class 转换为 'POSIXct'。
ESH5$Date <- as.POSIXct(ESH5$Date, format='%d/%m/%Y %H:%M:%S')
ESM5$Date <- as.POSIXct(ESM5$Date, format='%d/%m/%Y %H:%M:%S')
通过连接这些数据集的 'Date' 列得到 'min' 和 'max' 值。
MinD <- min(c(ESH5$Date, ESM5$Date))
MaxD <- max(c(ESH5$Date, ESM5$Date))
根据 'MinD' 和 'MaxD' 值创建日期时间序列作为新数据集
d1 <- data.frame(Date=seq(MinD, MaxD, by='sec'))
merge
所有数据集,方法是将它们放在 'list' 中并使用 Reduce
d2 <- Reduce(function(...) merge(..., by='Date', all=TRUE),
list(d1, ESH5, ESM5))
将 'd2' 数据集从 'wide' 重塑为 'long'
dLong <- reshape(d2, idvar='Date', varying=2:5, sep=".", direction='long')
dLong$time <- factor(dLong$time, labels=c('ESH5', 'ESM5'))
row.names(dLong) <- NULL
使用 dcast
library(reshape2)
res <- dcast(dLong, Date~time+Type, value.var='Price')
删除多余的 NA 列
res1 <- res[!grepl('NA', names(res))]
使用 zoo
中的 na.locf
用之前的非 NA 值填充 NA 值
library(zoo)
res1[-1] <- lapply(res1[-1], na.locf, na.rm=FALSE)
res1
# Date ESH5_Ask ESH5_Bid ESH5_Trade ESM5_Ask ESM5_Bid ESM5_Trade
#1 2015-10-22 09:00:00 NA 50.1 NA NA NA NA
#2 2015-10-22 09:00:01 NA 50.1 NA NA 50.09 NA
#3 2015-10-22 09:00:02 50.12 50.1 NA 50.11 50.09 NA
#4 2015-10-22 09:00:03 50.12 50.1 NA 50.11 50.09 NA
#5 2015-10-22 09:00:04 50.12 50.1 NA 50.11 50.09 50.09
#6 2015-10-22 09:00:05 50.12 50.1 NA 50.11 50.09 50.09
#7 2015-10-22 09:00:06 50.12 50.1 50.1 50.11 50.09 50.09
或者使用dplyr/tidyr
,我们可以使用spread
来改变每个数据集的格式,full_join
,它们与'd1'一起改变'NA' 每列中的值与使用 na.locf
和 mutate_each
的 'non-NA' 先前值。使用 paste
(如果需要)更改列名称。
library(dplyr)
library(tidyr)
library(zoo)
res2 <- full_join(spread(ESH5, Type, Price),
spread(ESM5, Type, Price), by='Date') %>%
full_join(d1, ., by='Date') %>%
mutate_each(funs(na.locf(., na.rm=FALSE)), -Date)
names(res2)[-1] <- c(paste('ESH5', sort(ESH5$Type),sep="_"),
paste('ESM5', sort(ESM5$Type), sep="_"))
res2
# Date ESH5_Ask ESH5_Bid ESH5_Trade ESM5_Ask ESM5_Bid ESM5_Trade
#1 2015-10-22 09:00:00 NA 50.1 NA NA NA NA
#2 2015-10-22 09:00:01 NA 50.1 NA NA 50.09 NA
#3 2015-10-22 09:00:02 50.12 50.1 NA 50.11 50.09 NA
#4 2015-10-22 09:00:03 50.12 50.1 NA 50.11 50.09 NA
#5 2015-10-22 09:00:04 50.12 50.1 NA 50.11 50.09 50.09
#6 2015-10-22 09:00:05 50.12 50.1 NA 50.11 50.09 50.09
#7 2015-10-22 09:00:06 50.12 50.1 50.1 50.11 50.09 50.09