Julia:如何修改已保存为二进制文件的矩阵列?

Lan*_*don 5 binary matrix save julia

我正在使用大型数据矩阵(Nrow x Ncol),这些数据太大而无法存储在内存中.相反,在我的工作领域中将数据保存到二进制文件中是标准的.由于工作的性质,我只需要一次访问矩阵的1列.我还需要能够修改列,然后将更新的列保存回二进制文件.到目前为止,我已经设法弄清楚如何将矩阵保存为二进制文件以及如何从二进制文件中读取矩阵的1'列'到内存中.但是,在我编辑列的内容后,我无法弄清楚如何将该列保存回二进制文件.

例如,假设数据文件是已保存到磁盘的32位标识矩阵.

Nrow = 500
Ncol = 325
data = eye(Float32,Nrow,Ncol)
stream_data = open("data","w")
write(stream_data,data[:])
close(stream_data)
Run Code Online (Sandbox Code Playgroud)

从磁盘读取整个文件,然后重新变换回矩阵非常简单:

stream_data = open("data","r")
data_matrix = read(stream_data,Float32,Nrow*Ncol)
data_matrix = reshape(data_matrix,Nrow,Ncol)
close(stream_data)
Run Code Online (Sandbox Code Playgroud)

正如我之前所说,我使用的数据矩阵太大而无法读入内存,因此上面编写的代码通常无法执行.相反,我需要一次使用1列.以下是将矩阵的1列(例如第7列)读入内存的解决方案:

icol = 7
stream_data = open("data","r")
position_data = 4*Nrow*(icol-1)
seek(stream_data,position_data)
data_col = read(stream_data,Float32,Nrow)
close(stream_data)
Run Code Online (Sandbox Code Playgroud)

请注意,'position_data'变量中的系数'4'是因为我正在使用Float32.另外,我不完全理解seek命令在这里做了什么,但它似乎根据以下测试给出了正确的输出:

data == data_matrix     # true
data[:,7] == data_col   # true
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,我想确定我加载的列(即第7列)需要用零替换:

data_col = zeros(Float32,size(data_col))
Run Code Online (Sandbox Code Playgroud)

现在的问题是弄清楚如何将此列保存回二进制文件而不影响任何其他数据.当然我打算用'write'来执行这个任务.但是,我不完全确定如何继续.我知道我需要从打开数据流开始; 但是我不确定我需要使用什么'模式':"w","w +","a"或"a +"?这是使用"w"失败的尝试:

icol = 7
stream_data = open("data","w")
position_data = 4*Nrow*(icol-1)
seek(stream_data,position_data)
write(stream_data,data_col)
close(stream_data)
Run Code Online (Sandbox Code Playgroud)

原始二进制文件(在我尝试编辑二进制文件失败之前)在磁盘上占用了650000个字节.这与矩阵的大小为500x325且Float32的数量占4个字节(即4*500*325 = 650000)的事实一致.但是,在我尝试编辑二进制文件后,我发现二进制文件现在只占用14000字节的空间.一些快速的心理数学表明,14000字节对应于7列数据(4*500*7 = 14000).快速检查确认二进制文件已使用大小为500x7的新矩阵替换了所有原始数据,其元素全部为零.

stream_data = open("data","r")
data_new_matrix = read(stream_data,Float32,Nrow*7)
data_new_matrix = reshape(data_new_matrix,Nrow,7)
sum(abs(data_new_matrix))  # 0.0f0
Run Code Online (Sandbox Code Playgroud)

为了仅修改二进制文件中的第7个"列",我需要做什么/更改?

Dan*_*etz 1

代替

icol = 7
stream_data = open("data","w")
position_data = 4*Nrow*(icol-1)
seek(stream_data,position_data)
write(stream_data,data_col)
close(stream_data)
Run Code Online (Sandbox Code Playgroud)

在OP中,写

icol = 7
stream_data = open("data","r+")
position_data = 4*Nrow*(icol-1)
seek(stream_data,position_data)
write(stream_data,data_col)
close(stream_data)
Run Code Online (Sandbox Code Playgroud)

即替换"w""r+"并且一切正常。

参考openhttp://docs.julialang.org/en/release-0.4/stdlib/io-network/#Base.open ,它解释各种模式。最好open不要与原始的有些令人困惑但绝对较慢的字符串参数一起使用。