与Python相比,阅读Julia中的大文本/ csv文件需要很长时间.以下是读取大小为486.6 MB且包含153895行和644列的文件的时间.
python 3.3的例子
import pandas as pd
import time
start=time.time()
myData=pd.read_csv("C:\\myFile.txt",sep="|",header=None,low_memory=False)
print(time.time()-start)
Output: 19.90
Run Code Online (Sandbox Code Playgroud)
R 3.0.2示例
system.time(myData<-read.delim("C:/myFile.txt",sep="|",header=F,
stringsAsFactors=F,na.strings=""))
Output:
User System Elapsed
181.13 1.07 182.32
Run Code Online (Sandbox Code Playgroud)
Julia 0.2.0(Julia Studio 0.4.4)示例#1
using DataFrames
timing = @time myData = readtable("C:/myFile.txt",separator='|',header=false)
Output:
elapsed time: 80.35 seconds (10319624244 bytes allocated)
Run Code Online (Sandbox Code Playgroud)
Julia 0.2.0(Julia Studio 0.4.4)示例#2
timing = @time myData = readdlm("C:/myFile.txt",'|',header=false)
Output:
elapsed time: 65.96 seconds (9087413564 bytes allocated)
Run Code Online (Sandbox Code Playgroud)
Julia比R快,但与Python相比相当慢.我可以做些什么来加快阅读大文本文件的速度?
另一个问题是内存中的大小是Julia中硬盘文件大小的18倍,但是python只有2.5倍大小.在Matlab中,我发现它对于大文件来说是最有效的内存,它是2 x大小的硬盘文件大小.Julia内存中文件大小的任何特殊原因?
Joh*_*ite 44
最好的答案可能是我不像韦斯那样优秀的程序员.
通常,DataFrames中的代码比Pandas中的代码更不优化.我相信我们可以赶上,但需要一些时间,因为我们需要首先实现许多基本功能.由于需要在Julia中构建太多,我倾向于专注于三个部分:(1)构建任何版本,(2)构建正确的版本,(3)构建快速,正确的版本.对于我的工作,Julia通常不会提供任何版本的基本功能,所以我的工作主要集中在(1)和(2)上.随着我需要构建的工具越多,关注性能就越容易.
至于内存使用情况,我认为答案是我们在解析表格数据时使用一组数据结构,这些表格数据的效率远低于Pandas使用的表格数据.如果我更好地了解熊猫的内部,我可以列出我们效率较低的地方,但是现在我只是推测一个明显的失败是我们将整个数据集读入内存而不是从磁盘中抓取块.这当然是可以避免的,并且存在这样的问题.这只是时间问题.
在这方面,readtable
代码很容易阅读.最readtable
快速的方法是甩掉Julia分析器并开始修复它发现的性能缺陷.
Mic*_*gge 11
我发现了一些可以部分帮助这种情况的事情.
使用readdlm()
Julia中的函数似乎工作得更快(例如,在最近的一次试验中是3倍)readtable()
.当然,如果你想要DataFrame对象类型,那么你需要转换为它,这可能会耗费大部分或全部的速度提升.
指定文件的尺寸可以在速度和内存分配方面产生巨大差异.我在磁盘上以258.7 MB的文件运行此试用版:
julia> @time Data = readdlm("MyFile.txt", '\t', Float32, skipstart = 1);
19.072266 seconds (221.60 M allocations: 6.573 GB, 3.34% gc time)
julia> @time Data = readdlm("MyFile.txt", '\t', Float32, skipstart = 1, dims = (File_Lengths[1], 62));
10.309866 seconds (87 allocations: 528.331 MB, 0.03% gc time)
Run Code Online (Sandbox Code Playgroud)对象的类型规范很重要.例如,如果您的数据中包含字符串,那么您读入的数组的数据将是Any类型,这是昂贵的内存.如果内存确实存在问题,您可能需要考虑通过首先将字符串转换为整数,进行计算,然后转换回来来预处理数据.此外,如果您不需要大量精度,使用Float32类型而不是Float64可以节省大量空间.您可以在读取文件时指定此项,例如:
Data = readdlm("file.csv", ',', Float32)
关于内存使用情况,我特别发现,如果您的数据有很多重复值,PooledDataArray类型(来自DataArrays包)可以帮助减少内存使用.转换为此类型的时间相对较大,因此这本身并不节省时间,但至少有助于减少内存使用量.例如,当加载具有1900万行和36列的数据集时,其中8列表示用于统计分析的分类变量,这将对象的内存分配从其在磁盘上的大小的5倍减小到其大小的4倍.如果存在更多的重复值,则内存减少可能更加显着(我已经在PooledDataArray将内存分配减少一半的情况下).
它有时也可以帮助gc()
在加载和格式化数据后运行(垃圾收集器)功能以清除任何不需要的ram分配,尽管Julia通常会很好地自动执行此操作.
尽管如此,尽管如此,我还是期待Julia的进一步发展,以便为大型数据集实现更快的加载和更高效的内存使用.
Jef*_*son 10
请注意,"n bytes allocated"输出来自@time
所有已分配对象的总大小,忽略了可能已释放的对象数.此数字通常远高于内存中活动对象的最终大小.我不知道这是你的记忆大小估计是基于什么,但我想指出这一点.
Jef*_*son 10
Jacob Quinn提供了一个名为CSV.jl的相对较新的julia软件包,它提供了更快的CSV解析器,在很多情况下与pandas相同:https://github.com/JuliaData/CSV.jl
Bog*_*ski 10
让我们首先创建一个您正在谈论的文件以提供可重复性:
open("myFile.txt", "w") do io
foreach(i -> println(io, join(i+1:i+644, '|')), 1:153895)
end
Run Code Online (Sandbox Code Playgroud)
现在我在 Julia 1.4.2 和 CSV.jl 0.7.1 中读取了这个文件。
单线程:
julia> @time CSV.File("myFile.txt", delim='|', header=false);
4.747160 seconds (1.55 M allocations: 1.281 GiB, 4.29% gc time)
julia> @time CSV.File("myFile.txt", delim='|', header=false);
2.780213 seconds (13.72 k allocations: 1.206 GiB, 5.80% gc time)
Run Code Online (Sandbox Code Playgroud)
并使用例如 4 个线程:
julia> @time CSV.File("myFile.txt", delim='|', header=false);
4.546945 seconds (6.02 M allocations: 1.499 GiB, 5.05% gc time)
julia> @time CSV.File("myFile.txt", delim='|', header=false);
0.812742 seconds (47.28 k allocations: 1.208 GiB)
Run Code Online (Sandbox Code Playgroud)
在 R 中是:
> system.time(myData<-read.delim("myFile.txt",sep="|",header=F,
+ stringsAsFactors=F,na.strings=""))
user system elapsed
28.615 0.436 29.048
Run Code Online (Sandbox Code Playgroud)
在 Python (Pandas) 中,它是:
>>> import pandas as pd
>>> import time
>>> start=time.time()
>>> myData=pd.read_csv("myFile.txt",sep="|",header=None,low_memory=False)
>>> print(time.time()-start)
25.95710587501526
Run Code Online (Sandbox Code Playgroud)
现在,如果我们fread
从 R(速度很快)进行测试,我们会得到:
> system.time(fread("myFile.txt", sep="|", header=F,
stringsAsFactors=F, na.strings="", nThread=1))
user system elapsed
1.043 0.036 1.082
> system.time(fread("myFile.txt", sep="|", header=F,
stringsAsFactors=F, na.strings="", nThread=4))
user system elapsed
1.361 0.028 0.416
Run Code Online (Sandbox Code Playgroud)
所以在这种情况下,总结是:
CSV.File
第一次运行 Julia的编译成本很高,但它比基本的 R 或 Python 快得多fread
与 R相当(在这种情况下稍慢,但此处制作的其他基准测试显示速度更快的情况)编辑:根据请求,我为一个小文件添加了一个基准:10 列,100,000 行 Julia 与 Pandas。
数据准备步骤:
open("myFile.txt", "w") do io
foreach(i -> println(io, join(i+1:i+10, '|')), 1:100_000)
end
Run Code Online (Sandbox Code Playgroud)
CSV.jl,单线程:
julia> @time CSV.File("myFile.txt", delim='|', header=false);
1.898649 seconds (1.54 M allocations: 93.848 MiB, 1.48% gc time)
julia> @time CSV.File("myFile.txt", delim='|', header=false);
0.029965 seconds (248 allocations: 17.037 MiB)
Run Code Online (Sandbox Code Playgroud)
熊猫:
>>> import pandas as pd
>>> import time
>>> start=time.time()
>>> myData=pd.read_csv("myFile.txt",sep="|",header=None,low_memory=False)
>>> print(time.time()-start)
0.07587623596191406
Run Code Online (Sandbox Code Playgroud)
结论:
现在,如果您想避免在每个新的 Julia 会话上支付编译成本,这可以通过https://github.com/JuliaLang/PackageCompiler.jl 实现。
根据我的经验,如果你在做数据科学工作,比如你读入了数千个 CSV 文件,我不会有等待 2 秒编译的问题,如果稍后我可以节省几个小时。编写读取文件的代码需要 2 秒多的时间。
当然 - 如果您编写的脚本几乎没有工作并在完成后终止,那么这是一个不同的用例,因为编译时间实际上将占计算成本的大部分。在这种情况下,使用 PackageCompiler.jl 是我使用的一种策略。
根据我的经验,处理较大文本文件的最佳方法是不将它们加载到Julia中,而是将它们流式传输.这种方法有一些额外的固定成本,但通常运行速度非常快.一些伪代码是这样的:
function streamdat()
mycsv=open("/path/to/text.csv", "r") # <-- opens a path to your text file
sumvec = [0.0] # <-- store a sum here
i = 1
while(!eof(mycsv)) # <-- loop through each line of the file
row = readline(mycsv)
vector=split(row, "|") # <-- split each line by |
sumvec+=parse(Float64, vector[i])
i+=1
end
end
streamdat()
Run Code Online (Sandbox Code Playgroud)
上面的代码只是一个简单的总和,但这个逻辑可以扩展到更复杂的问题.