如何在Julia中写入和读取包含datetime列的数据帧

如何在Julia中写入和读取包含datetime列的数据帧,datetime,dataframe,hdf5,julia,Datetime,Dataframe,Hdf5,Julia,第二次更新:用户@Matt B确认为一个bug。有关更多详细信息,请参见下面的答案 更新:@waTeim已经证明,可以写入和读取包含日期类型列的数据帧(在我的设置中确认)。这很重要,因为这意味着Julia可以写入和读取数据帧列中的某些复合类型。但是,datetime类型(与date类型不同)仍然会抛出一个错误,因此在这一点上问题仍然没有答案 在Julia中,使用HDF5和JLD包,可以在.JLD文件中保存和加载数据帧,例如: #Preamble using HDF, JLD, DataFrame

第二次更新:用户@Matt B确认为一个bug。有关更多详细信息,请参见下面的答案

更新:@waTeim已经证明,可以写入和读取包含日期类型列的数据帧(在我的设置中确认)。这很重要,因为这意味着Julia可以写入和读取数据帧列中的某些复合类型。但是,datetime类型(与date类型不同)仍然会抛出一个错误,因此在这一点上问题仍然没有答案

在Julia中,使用HDF5和JLD包,可以在.JLD文件中保存和加载数据帧,例如:

#Preamble
using HDF, JLD, DataFrames
filePath = "/home/colin/Test.jld";

#Save the data-frame
fid1 = jldopen(FP, "w");
write(fid1, "MyDataFrame", MyDataFrame);
close(fid1);

#Come back later and load the data-frame
fid1 = jldopen(FP, "r");
X = read(fid1, "MyDataFrame");
close(fid1);
只要数据帧的列都是基本Julia类型的向量,如
Float64
Int64
,这种方法就可以很好地工作。但是,在实践中,我们通常希望数据帧的第一列是
日期时间
,它不是基类型(尽管在将来的版本中可能会成为基类型)。在这种情况下,上面的代码在
read
操作中失败,并显示一条很长的错误消息(如果有人在评论中询问,我会将其添加到底部)。根据JLD软件包的文档,我在保存时尝试了以下操作:

#Save the data-frame
fid1 = jldopen(FP, "w");
addrequire(fid1, "/home/colin/.julia/v0.2/DataFrames/src/dataframe.jl")
addrequire(fid1, "/home/colin/.julia/v0.2/Datetime/src/Datetime.jl")
write(fid1, "MyDataFrame", MyDataFrame);
close(fid1);
但这没有帮助

我是在做一些愚蠢的事情,还是这个功能根本不可用


注意:包含HDF5标记是因为JLD软件包使用它。

当缺少对特定数据类型的HDF5支持时,可能会出现此错误。在本例中,并不是特别使用Datetime的DataFrames,而是缺少对Datetime类型本身的支持。显然,当库由于任何原因(以及其他示例)无法加载类型时。每种类型的确切原因和修复都不同,但报告错误会导致提示修复(见下文)

错误 历史的 版本0.2.25 我建议您迁移到Julia版本0.3,因为它现在处于发行候选状态,并更新您的包存储库。我的设置不同;我使用不同版本的HDF5、JLD、数据帧和日期时间。但话说回来,我所做的两个重要更改只是在调用addrequire时指示模块名而不是文件名,并且还使用@read@write宏,而不是相应的函数,因为后者似乎有缺陷

Version 0.3.0-rc1+4263 (2014-07-19 02:59 UTC)

Pkg.status()
- DataFrames                    0.5.7
- HDF5                          0.2.25
- Datetime                      0.1.6
创建数据文件

using HDF5,JLD,DataFrames,Datetime

testFile = jldopen("test.jld","w")
addrequire(testFile,"DataFrames")
addrequire(testFile,"Datetime")
df = DataFrame()
df[:column1] = today() 
@write testFile df
close(testFile)
重新启动茱莉亚和阅读

julia> using HDF5,JLD,DataFrames,Datetime

julia> testFile = jldopen("test.jld","r")
Julia data file version 0.0.2: test.jld

julia> @read testFile df
1x1 DataFrame
|-------|------------|
| Row # | column1    |
| 1     | 2014-07-19 |

julia> df[:column1]
 1-element DataArray{Date{ISOCalendar},1}:
 2014-07-19
版本0.2.25+(预发布) 事实上,我可以证实,试图存储Datetime失败了,使用回购协议中的最新版本解决了这个问题

 HDF5                          0.2.25+            master
如果仅通过将今天的更改为现在的()

接下来

julia> using HDF5,JLD,DataFrames,Datetime

julia> testFile = jldopen("test.jld","r")
Julia data file version 0.0.2: test.jld

julia> @read testFile df
1x1 DataFrame
|-------|-------------------------|
| Row # | column1                 |
| 1     | 2014-07-26T03:38:45 UTC |
但是,Datetime中出现的相同的一般性错误消息也会出现在复杂类型中

版本0.2.26 此版本还支持复杂的。最初看来,这个问题通常缺乏对complex类型的支持,但更可能是从1+im初始化complex的特殊问题;而不是1.0+im


正如我在上面的评论中所指出的,这就是现在已经发生的行为。在0.2.26版本被标记之前,您可以使用
Pkg.checkout(“HDF5”)
来修复此错误


但为了让这更像一个答案,我将更详细地描述这个问题,并给出一个潜在的解决方法。
Date
DateTime
类型都是带有。在HDF5.jl包中保存和加载bitstypes是一项相对较新的功能;仅支持(标记为版本0.2.24和0.2.25)

这些版本有一个bug,其中BitStype的类型名不能与其模块名(作为完全限定的类型名)一起保存。您可以在
导入
使用
之间的区别中非常清楚地看到这一点:

julia> using HDF5, JLD # version 0.2.25

julia> import Datetime

julia> save("today.jld","t",Datetime.today()) # today() returns a `Datetime.Date`

julia> load("today.jld") # But it was saved as just a `Date`, not a `Datetime.Date`
                         # so HDF5 cannot find the definition
HDF5-DIAG: Error detected in HDF5 (1.8.11) thread 0:
  #000: H5Dio.c line 182 in H5Dread(): can't read data … # backtrace truncated

julia> using Datetime # Bring `Date` into the `Main` namespace

julia> load("today.jld") # now it works!
Dict{Union(UTF8String,ASCIIString),Any} with 1 entry:
  "t" => 2014-07-25
因此,当您要保存
日期时间
对象时,它由
日历
和时区偏移量参数化。但是,
Offset
类型并不是从Datetime包中导出的……它们有很多!但是,大多数日期时间只使用
Zone0
:UTC。因此,如果您使用HDF5.jl版本0.2.24-25保存了日期时间数据,则可以通过手动将这些类型“导出”到主命名空间来恢复数据

julia> save("now.jld","n",now())

julia> load("now.jld")
HDF5-DIAG: Error detected in HDF5 (1.8.11) thread 0:
  #000: H5Dio.c line 182 in H5Dread(): can't read data … # truncated

julia> const Zone0 = Datetime.Zone0;

julia> load("now.jld")
Dict{Union(UTF8String,ASCIIString),Any} with 1 entry:
  "n" => 2014-07-25T13:45:45 UTC

序列化()和反序列化()是否有可能满足您的需要?你不会得到一个.jld,但你应该能够做i/o。@Mageek
serialize()
deserialize()
可能可以工作,但从长远来看,解决方案是不可行的,因为不同版本的Julia或甚至运行在不同系统上的Julia实例可能无法读回写入的相同数据。不过谢谢你的想法,很抱歉我花了这么长时间才回复。这是一个bug。报告时间:现在应该修复!如果您仍然有问题,请告诉我(在标记新版本的HDF5之前,您可以使用
Pkg.checkout(“HDF5”)
获取此修补程序)。@MattB。谢谢Matt,我已经确认了我的设置。现在都在工作。如果你想写一个非常简短的答案,表明这是一个bug,并且已经修复,我会投票并给出答案。谢谢你的回复。我明天会试试这个。很有趣。您的示例很有效,但我认为这是因为您使用的是type
Date
,而不是
Datetime
,即
typeof(today())
返回
Date{ISOCalendar}
。如果将示例中的
df[:column1]=today()替换为
df[:column1]=datetime(2001,1,1,1,1,1)
那么我相信你会看到我看到的错误。我应该向其他读者澄清:这很有趣,因为类型
Date
也是
Datetime
包的一部分。这意味着问题具体在于
c = 1 + im;
@write testFile c
- HDF5                          0.2.26

julia> using HDF5, JLD

julia> testFile = jldopen("test.jld","r")
Julia data file version 0.0.2: test.jld

julia> @read testFile c
1 + 1im
julia> using HDF5, JLD # version 0.2.25

julia> import Datetime

julia> save("today.jld","t",Datetime.today()) # today() returns a `Datetime.Date`

julia> load("today.jld") # But it was saved as just a `Date`, not a `Datetime.Date`
                         # so HDF5 cannot find the definition
HDF5-DIAG: Error detected in HDF5 (1.8.11) thread 0:
  #000: H5Dio.c line 182 in H5Dread(): can't read data … # backtrace truncated

julia> using Datetime # Bring `Date` into the `Main` namespace

julia> load("today.jld") # now it works!
Dict{Union(UTF8String,ASCIIString),Any} with 1 entry:
  "t" => 2014-07-25
julia> save("now.jld","n",now())

julia> load("now.jld")
HDF5-DIAG: Error detected in HDF5 (1.8.11) thread 0:
  #000: H5Dio.c line 182 in H5Dread(): can't read data … # truncated

julia> const Zone0 = Datetime.Zone0;

julia> load("now.jld")
Dict{Union(UTF8String,ASCIIString),Any} with 1 entry:
  "n" => 2014-07-25T13:45:45 UTC