从长格式到宽格式的转换会产生重复的时间标识符行

Long to wide format conversion gives duplicate time identifier rows

请在投票结束前查看聊天记录

我有以下数据:

> dput(head(q,10))
structure(list(Date = structure(c(1471424400, 1471424400, 1471424400, 
1471424401, 1471424401, 1471424406, 1471424407, 1471424415, 1471424417, 
1471424514), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
    Type = c("ASK", "BID", "ASK", "BID", "ASK", "ASK", "BID", 
    "BID", "BID", "ASK"), Price = c(1749.95, 1611, 1683.9, 1653, 
    1672, 1683.9, 1653, 1654.2, 1663, 1682)), .Names = c("Date", 
"Type", "Price"), row.names = c(NA, -10L), class = c("tbl_df", 
"tbl", "data.frame"))

然后我使用了下面的代码:

data.new <- group_by(head(q,10), Date, Type) %>% summarize(price=ifelse(Type[1] == 'ASK', min(Price)

然后用

dputed<-dput(ungroup(data.new))


dput(dputed)
structure(list(Date = structure(c(1471424400, 1471424400, 1471424401, 
1471424401, 1471424406, 1471424407, 1471424415, 1471424417, 1471424514
), class = c("POSIXct", "POSIXt"), tzone = "UTC"), Type = c("ASK", 
"BID", "ASK", "BID", "ASK", "BID", "BID", "BID", "ASK"), price = c(1683.9, 
1611, 1672, 1653, 1683.9, 1653, 1654.2, 1663, 1682)), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -9L), .Names = c("Date", 
"Type", "price"))

我想将其转换为宽格式,其中 日期、报价和报价是三列,行包含特定时间戳的报价和报价值。 这是我试过的:

m.q<-dcast(dputed,Date ~ Type, value.var = "price")

但是结果有重复的时间戳。请注意相邻两行中的时间戳 (2016-08-17 09:00:06)。由于 bid 和 aks 不在同一行:

> dput(m.q)
structure(list(Date = structure(c(1471424400, 1471424401, 1471424406, 
1471424407, 1471424415, 1471424417, 1471424514), class = c("POSIXct", 
"POSIXt"), tzone = "UTC"), ASK = c(1683.9, 1672, 1683.9, NA, 
NA, NA, 1682), BID = c(1611, 1653, NA, 1653, 1654.2, 1663, NA
)), .Names = c("Date", "ASK", "BID"), row.names = c(NA, -7L), class = "data.frame")

请注意,当我使用 complete.cases() 时,我只得到 2 行而不是 3 行,因为 2016-08-17 09:00:06 被删除,因为出价和要价被分成两行相同的时间戳。

johny<- m.q[complete.cases(m.q),]
> dput(johny)
structure(list(Date = structure(c(1471424400, 1471424401), class = c("POSIXct", 
"POSIXt"), tzone = "UTC"), ASK = c(1683.9, 1672), BID = c(1611, 
1653)), .Names = c("Date", "ASK", "BID"), row.names = 1:2, class = "data.frame")

见下方编辑:

您提供的代码没有表现出您声称的行为:

m.q
                 Date    ASK    BID
1 2016-08-17 09:00:00 1683.9 1611.0
2 2016-08-17 09:00:01 1672.0 1653.0
3 2016-08-17 09:00:06 1683.9     NA
4 2016-08-17 09:00:07     NA 1653.0
5 2016-08-17 09:00:15     NA 1654.2
6 2016-08-17 09:00:17     NA 1663.0
7 2016-08-17 09:01:54 1682.0     NA

使用查看命令:

View(m.q)

让我们只检查该列:

m.q$Date
[1] "2016-08-17 09:00:00 UTC" "2016-08-17 09:00:01 UTC" "2016-08-17 09:00:06 UTC"
[4] "2016-08-17 09:00:07 UTC" "2016-08-17 09:00:15 UTC" "2016-08-17 09:00:17 UTC"
[7] "2016-08-17 09:01:54 UTC"

还要检查重复项:

duplicated(m.q$Date)
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE

没有其他方式可以告诉您您提供的数据没有重复。

编辑

按住按钮!暂时不要删除。显示器有问题。收到您的原始数据后:

library(readxl)
q <- read_excel("~/Data/3_day_1_stock.xlsx", sheet=1, skip=1)
dput(head(q, 10))
# # A tibble: 10 x 3
#                   Date  Type   Price
#                 <time> <chr>   <dbl>
# 1  2016-08-17 09:00:00   ASK 1749.95
# 2  2016-08-17 09:00:00   BID 1611.00
# 3  2016-08-17 09:00:00   ASK 1683.90
# 4  2016-08-17 09:00:01   BID 1653.00
# 5  2016-08-17 09:00:01   ASK 1672.00
# 6  2016-08-17 09:00:06   ASK 1683.90
# 7  2016-08-17 09:00:06   BID 1653.00
# 8  2016-08-17 09:00:14   BID 1654.20
# 9  2016-08-17 09:00:17   BID 1663.00
# 10 2016-08-17 09:01:54   ASK 1682.00

第 6 行和第 7 行的日期似乎重复了。但进一步检查它们是不同的:

dput(head(q, 10))
structure(list(Date = structure(c(1471424400, 1471424400, 1471424400, 
1471424401, 1471424401, 1471424406, **1471424407**__, 1471424415, 1471424417, 
1471424514), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
    Type = c("ASK", "BID", "ASK", "BID", "ASK", "ASK", "BID", 
    "BID", "BID", "ASK"), Price = c(1749.95, 1611, 1683.9, 1653, 
    1672, 1683.9, 1653, 1654.2, 1663, 1682)), .Names = c("Date", 
"Type", "Price"), row.names = c(NA, -10L), class = c("tbl_df", 
"tbl", "data.frame"))

我们可能需要写一份问题报告。

以下是聊天后的观察结果。重要的是要注意由于 excel 导入而出现的问题。

首先,重要的是要了解 excel 如何在内部存储 date/time 值,它们(如果您打开 sheet xml 文件)看起来像42599.3750694444 其中整数部分是自 1900 年 1 月 1 日以来的天数,小数部分是当天 24 小时(86400 秒)的分数(百分比)。

当我们将其导入 R 时,您需要将此格式转换为 unix 格式(自 1970 年 1 月 1 日以来的秒数)。

显然有通常的 Floating Point approximation,如果您使用 sprintf:

获取值,它是可见的
> sprintf("%.10f",t$Date[5:8])
[1] "1471424401.0000002384" "1471424406.0000002384" "1471424406.9999997616" "1471424414.9999997616"

接下来发生的是当你 'print' 一个 POSIXct 值时,底层代码使用 C 库中的 time.h,其中 time_t 应该是一个秒数。问题出现了 here 我认为,该值被截断为其整数部分,因此显示错误的 9:00:06 时间而不是 9:00:07.

R 中的

POSIX 类 应该处理小数秒,但您只能以 strftime:

的自定义格式查看它们
> strftime(t$Date[5:8],"%Y/%m/%d %H:%M:%OS6")
[1] "2016/08/17 11:00:01.000000" "2016/08/17 11:00:06.000000" "2016/08/17 11:00:06.999999" "2016/08/17 11:00:14.999999"

您主要关心的是为不同的值打印同一秒,其余函数按预期工作,对第 6 行和第 7 行使用不同的值,因为它们确实不同。

我看到了两种可能的解决方法:

  1. 将列转换为数字,四舍五入,转换回 POSIXct:

    t$Date <- as.POSIXct(round(as.numeric(t$Date)),origin='1970-01-01',tz='UTC')
    
  2. 将您的 excel sheet 导出到 csv,使用 read_csv 导入它,然后将日期列转换为日期:

    z <- read.csv2("c:/Downloads/3_day_1_stock.csv", skip=1, stringsAsFactors=FALSE)
    z$Date <- as.POSIXct(z$Date,format="%m/%d/%Y %H:%M:%S",tz='UTC')
    

对于所有情况,使用 skip=1 作为 read_* 的参数来跳过第一行,而不是您的 dput hack,然后函数将检测到正确的列。