Hybrid Apache arrow / numpy dataframe与vaex版本4.0

2021-03-11 02:38:54

VAEX DataFrame一直非常快。从地面上构建的核心(磁盘的大小是限制),它推动了在大数据分析的上下文中可以做的单个机器的限制。从版本2开始,我们为字符串添加了更好的支持数据,与熊猫相比,近1000倍的加速。为了支持这一看似微不足道的数据类型,我们必须选择磁盘和内存格式,并且不想重新发明轮子。 Apache arrow是一个明显的选择,但没有达到当时的要求。但是,我们仍然在VAEX中添加了字符串支持,但是以未来的兼容方式,使时间到达(现在!),我们可以采用Apache箭头而不从过去过时的数据呈现数据,或者需要数据转换。为了与Apache arrow兼容,我们开发了Vaex-arrow包,它以vaex平滑为互操作性,以可能的内存复制在此处和那里。

使用Apache arrow版本3.0该时间已经到来将箭头支持集成到Vaex的核心(Python包vaex-core),弃用了Vaex-arrow包。虽然所有版本的VAEX都支持磁盘上的相同字符串数据(在HDF5或Apache arrow格式中),VAEX版本4.0中的不同之处在于我们现在将这些传递为箭头阵列。

导入vaexdf = vaex.from_arrays(库= [' vaex' numpy&#39 ;,' apache arrow'])打印(df)#####198 ' vaex' ## 1' numpy' ## 2' Apache arrow'打印(DF ['图书馆'价值观)) ##& ampltpyarrow.lib.stringArray对象在0x7f631c1a1360& ampgt ## [##" vaex" numpy",##" Apache arrow" ##]

导入vaeximport numpy作为npimport pyarrow作为pax = np.arange(4)y = pa.array([42,12,144,1024])df = vaex.from_arrays(x = x,y = y)df [&#39 ; y'] = df.x * df.yprint(Rep(df.y))##表达式= y ##长度:4 dtype:对象(列)## ---------- ---------------------- ## 0 0 ## 1 12 ## 2 288 ## 3072

虽然默认情况而言,arrow采用熊猫样方法将缺失值转换为Num,在Numpy中混合时,在VAEX中,我们确保您的缺失值保持缺失值,并且由于此,您的阵列不会浮动到浮动。

导入vaeximport numpy作为npimport pyarrow作为pax = np.ma.array(np.arange(4),mask = [0,1,0,0],dtype =' i4')y = pa.array ([42,12,144,无],type = pa.int32())#现在我们得到naN(不是一个数字)打印(x * y)## [0.0 - 288.0 naN] df = vaex.from_arrays( x = x,y = y)df [' y'] = df.x * df.y#vaex传播缺少的值图('df.y))##表达式= Y ##长度:4 dtype:int64(列)## --------------------------- ## 0 0 ## 1 - ## 2 288 ## 3 -

我们不仅在vaex的核心库中采用了apache arrow,但我们也是从vaex到arrow.compute的快速字符串算法。结果,我们不仅具有数据的互操作性,而且对字符串数据的操作也是相同的语义。这意味着VAEX,PANDAS,DASK DataFrame都可以以相同的方式运行相同的数据。这项工作由Chan Zuckerberg计划赞助,我们感谢汤姆Aupspulger组织这一点。

虽然对数值和字符串数据的支持获取了大多数工作,但Apache arrow都支持更有趣的数据结构。对于实例,拆分字符串会导致字符串中的结果。该数据结构非常适合高位性能(连续布局与许多小缓冲区),仍然允许我们像常规字符串阵列一样操作。这意味着我们可以拆分/令授权字符串,并且像条带上的扫描程序,而无需通过加入并拆分,每次:

导入vaexdf = vaex.from_arrays(text = ['所以,你可以分开这个吗?&#39 ;,'',none] df.text.split(& #34;")##表达式= str_split(文本,'')##长度:3 dtype:list& solltitem:string& ampgt(表达式)## ------ ----------------------------------- ## 0 ['所以,&#39 ;,'可以&#39 ;,'你&#39 ;,' split','这个?'] ## 1 [& #39;和''这个。'] ## 2 - #将字符串操作应用于listdf.text.split中的每个字符串("") .str.strip(',?。'))##表达式= str_strip(str_split(文本,''),',?。') ##长度:3 dtype:list& solltitem:string& ampgt(表达式)## ---------------------------- ---------------- ## 0 [' SO&#39 ;,'可以'你'你&#39 ;,&# 39;拆分''这个'] ## 1 ['和''这个'] ## 2 -

String Splitting甚至可以多次创建嵌套列表而没有任何性能损失。

df.text.stlit("")。str.strip(',?。')。str.split(' a')##表达= str_split(str_split(str_split(文本,''),',?。'),' a')##长度:3 dtype:list&amp ; AmplTitem:List& SollTitem:String& Ampgt& Ampgt(表达)## ---------------------------------- ------------------------- ## 0 [[' SO'],[' C&#39 ;,' n'],['你'],[' split'],['这个']] ## 1 [[ '和'],['这个']] ## 2 -

Apache arrow将为整个数据分析世界带来很多好的,而不仅仅是Python。它速度快速增长,快速移动,我们相信将成为Python的分析的未来,补充或替代许多领域的Numpy。但是,采用将需要时间,大多数人可能更舒适地看到Numpy阵列。因此,VAEX版本4 DataFrame可以按住NumPy阵列和Apache箭头阵列,以使转换周期更轻松。如果数据来自HDF5文件或从外部NumPy阵列中,我们将其保留为Numpy数组,但字符串除外数据来自箭头文件或外部箭头阵列,我们将它们保留为箭头阵列。

如果您碰巧有箭头文件,但更喜欢使用Numpy阵列(由于计算语义),您可以懒惰地转换所有数据,但字符串数据除外。

使用Apache arrow出来的核心镶木地板支持,是一个非常好的要求。虽然以前版本的Vaex-arrow提供了一些镶木地板支持,但我们现在支持延迟加载,允许您通过比内存大的镶木数据集扫描。虽然木地板将以某些CPU的成本来,但其尺寸减少使其成为云存储的有吸引力的格式,其中网络带宽通常是限制因素。

使用Apache arrow的额外好处是支持读取分区的地形文件。这非常方便,因为从火花/ Hadoop世界生成的文件经常以这种格式出现,因此从这些平台更轻松地摄取。

我们还支持创建分区文件,可能不是VAEX最表现的部分,但我们使用它进行测试,并认为分享将是好的。

导入vaexcountries = ['美国'我们'我们' nl&#39 ;,' fr&#39 ;,' nl',' nl&#39 ;, #39; nl']年= [2020,2021,2020,2020,2021,2020,2020,2019,2020]值= [1,2,3,4,5,6] df = vaex.from_dict({'国家& #39 ;:国家,'年&#39 ;:岁,' value'值,})df.export_partitioned(' ./ partitioned',by = [&# 39;国家','年'])#### $ ls -r ./partitioned/##./partitioned/::##' vountry=fr' '国家= nl' '国家=美国' ####' ./分区/国家= fr':##'年= 2020' ####' / partitioned/country=fr/year=2020' :###db5f59db-f207-4dca-8999-e405436c3a88.parquet####' ;;/partitioned/country=nl' ;:##&# 39;年= 2019年' '年= 2020' ####' ./分区/国家/地区= NL /年= 2019':## EE1B5558-E1C7-4D49-A899-A0B6C29ACE00.PARQUET #### ' ./ partented / country = nl /年= 2020':## 3908d92f-d280-4c83-9e51-bead619d470b.parquet ####' ./ partitioned / country =美国' :##'年= 2020' '年= 2021' ####' ./分区/国家=美国/年= 2020':## 8be82725-C46D-40AD-B2E4-BD3962469394.Parquet #### ' ./分区/国家=美国/年= 2021':## F4743B01-9783-4EF1-8BFF-E892C050A50A.PARQUET

如果分区以Hive格式为以蜂巢格式,则很好,只需打开目录:

导入vaexdf = vaex.open(' ./分区/')打印(df)##%国家年## 0 4' fr' 2020 ## 1 5' nl' 2019 ## 2 3' nl' 2020 ## 3 6' nl' 2020 ## 4 1'我们' 2020 ## 5 2'美国' 2021.

导入vaexdf.export_partitioned(' ./ partitioned_directory /' by = ['国家''年和#39;],directory_format =' {value}& #39;)vaex.open(' ./ partitioned_directory /',partitioning = ['国家/地区'年和#39;])打印(df)###价值国家一年## 0 4' fr' 2020 ## 1 5' nl' 2019 ## 2 3' nl' 2020 ## 3 6' nl' 2020 ## 4 1'我们' 2020 ## 5 2'美国' 2021.

在版本4.0中,VAEX支持与DASK,RAY或PYTHON' S多处理库进行集成的酸洗,显着更轻松。

虽然您可能用于酸洗是一种非有效的方式或存储数据,但在许多情况下,VAEX不会纠正数据本身。当我们做的时候:

导入vaeximport pickledf = vaex.open(' s3://vaex/taxi/nyc_taxi_2015_mini.parquet& n39;)df [' tip_percentage'] = df.tip_amount / df.total_amountn = len(df )打印(f' {n:,}行')## 300,000 Rowswith打开(' mydataframe.pickle' wb')作为f:pickle.dump( df,f)## $ ls -alh ./mydataframe.pickle## -rw-rw-r-- 1 maartenbreddels maartenbreddels 907 12月1日16:24 ./mydataframe.pickle

你可能会惊讶的是,这只是907字节!如果您检查文件,您会注意到我们纠正了路径和内部状态(例如虚拟列DF.TIP_AMOUNT / DF.Total_AMOUNT)。

当您希望将整个Dataframe存储到磁盘时,这可能非常有用,或通过电线发送它。我们只需纠正原始文件位置和您所做的所有操作(转换和过滤),而不是复制1大字节。请注意,这对云存储特别好,因为所有计算机的文件位置都是相同的。

虽然VAEX我们主要专注于获得一个强大的机器的最大性能,但这为您真正需要群集的那些情况铺平了优化的分布式计算的方式。

认识到df.apply是一个逃生舱口,这是必要的完成物品,我们也必须认识到与其他vaex相比,这是痛苦的缓慢,降至100%的CPU使用率。这里的瓶颈是由全球翻译锁(GIL)造成的,而不是直接vaex造成的。尽管如此,我们觉得我们应该尝试找到一种提高应用方法性能的方法。

导入vaexdef is_prime(x):返回x> 1和全部((x%i)!= 0在范围内(2,x))df = vaex.from_arrays(x = vaex.vrange(0,100_000,dtype =' i4')) #您需要明确地指定您需要的参数[' is_prime'] = df.apply(aramimes = [df.x])df.head(10)###x is_prime ## 0 0 false ## 1 1 false ## 2 2真实## 3 3真## 4 4假## 5 5真## 6 6假## 7 7真## 8 8假## 9 9 false

虽然在早期的VAEX版本中存在对HDF5的S3支持,但由于Apache Arrow和FSSPEC项目,我们进一步改进了这一点。 VAEX可以读取并将大多数文件格式读到许多云存储系统,最表现为S3。对于S3和Google云存储,我们本身支持他们的文件路径,例如" s3://vaex/testing/xys.hdf5",或" gc://vaex/testing/xys.hdf5& #34;在所有其他情况下,可以通过Apache箭头或FSSpec指定文件系统对象。

导入vaexdf = vaex.open(' s3://vaex/testing/xys.hdf5')df = vaex.open(' gc://vaex/testing/xys.hdf5' )#使用apache arrow连接到Hadoop文件systemimport pyarrow.fs作为fshdfs = fs.hadoopfilesystem(host,port)df = vaex.open(' myfile.parquet' fs = hdfs)#或fsspec使用httpimport fsspechttps = fsspec.filesystem(' https' https')df = vaex.open(' https://cdn.gea.esac.esa.int/gaia/gedr3/gaia_source/gaiasource_000000- 003111.csv.gz',fs = http)

我们希望您对4.0张vaex发布时感到兴奋。统一Apache箭头和Numpy在单个DataFrame库中,我们丰富的数据结构(例如字符串列表),与Numpy,互操作性(零复制数据共享)和整体光明的未来兼容。核心外的木质支撑在一起大量改进的云存储支持使得与云一起使用并更透明。改进的泡沫支持和默认并行应用允许在需要诉诸纯Python代码时更好的性能。

#想要安装?$ pip安装" vaex == 4。*"#只想核心功能?$ pip安装" vaex-core == 4。*"#使用公园或曼巴(Mamba)?$ Conda安装-c conda-forge vaex = 4

在HTTPS://github.com/vaexio/vaex上加入我们的GitHub,如果要为更多常规问题提供贡献或查找问题,或查找问题,或https://github.com/vaexio/vaex/discussions。

您需要帮助加速您的数据处理或数据分析吗?联系我们看看我们是否可以帮助您。