簡體   English   中英

加載多個鑲木地板文件時保留 dask 數據幀分區

[英]Preserving dask dataframe divisions when loading multiple parquet files

我在數據框中有一些時間序列數據,以時間為索引。 索引已排序,數據存儲在多個 parquet 文件中,每個文件中包含一天的數據。 我使用 dask 2.9.1

當我從一個鑲木地板文件加載數據時,分區設置正確。

當我從多個文件加載數據時,我在生成的 dask 數據框中沒有得到這些設備。

下面的例子說明了這個問題:

import pandas as pd 
import pandas.util.testing as tm
import dask.dataframe as dd

df = tm.makeTimeDataFrame( 48, "H")

df1 = df[:24].sort_index()
df2 = df[24:].sort_index()
dd.from_pandas( df1, npartitions=1 ).to_parquet( "df1d.parq", engine="fastparquet" ) 
dd.from_pandas( df2, npartitions=1 ).to_parquet( "df2d.parq", engine="fastparquet" )
ddf = dd.read_parquet( "df*d.parq", infer_divisions=True, sorted_index=True, engine="fastparquet"  ) 
print(ddf.npartitions, ddf.divisions)

在這里我得到 2 個分區和(None, None, None)作為分區

我可以使用 dd.read_parquet 將分區設置為實際值嗎?


更新

在我的實際數據中,我有一個鑲木地板文件 pr day。

這些文件是通過保存數據幀中的數據來創建的,其中時間戳用作索引。 索引已排序。 每個文件的大小為 100-150MB,當加載到內存中時,它使用應用程序 2.5GB 的 RAM,激活索引很重要,因為重新創建索引非常繁重。

我沒有設法在 read_parquet 上找到參數或引擎的組合,使其在加載時創建除法。

數據文件被命名為“yyyy-mm-dd.parquet”,所以我綁定到根據該信息創建分區:

from pathlib import Path
files = list (Path("e:/data").glob("2019-06-*.parquet") )
divisions = [  pd.Timestamp( f.stem) for f in files ] + [ pd.Timestamp( files[-1].stem) + pd.Timedelta(1, unit='D' ) ]
ddf = dd.read_parquet( files )
ddf.divisions = divisions

這並沒有啟用索引的使用,並且在某些情況下它失敗了“TypeError: can only concatenate tuple (not “list”) to tuple”

然后我嘗試將分區設置為元組ddf.divisions = tuple(divisions)然后它起作用了。 當索引設置正確時,dask 非常快


更新 2

更好的方法是單獨讀取 dask 數據幀,然后將它們連接起來:

from pathlib import Path
import dask.dataframe as dd
files = list (Path("e:/data").glob("2019-06-*.parquet") )
ddfs = [ dd.read_parquet( f ) for f in files ]
ddf = dd.concat(ddfs, axis=0)

通過這種方式設置了分區,它還解決了隨着時間的推移處理添加列的另一個問題。

下面我把原來的問題改寫為concat,解決了我的問題

import pandas as pd 
import pandas.util.testing as tm
import dask.dataframe as dd

# create two example parquet files
df = tm.makeTimeDataFrame( 48, "H")
df1 = df[:24].sort_index()
df2 = df[24:].sort_index()
dd.from_pandas( df1, npartitions=1 ).to_parquet( "df1d.parq" ) 
dd.from_pandas( df2, npartitions=1 ).to_parquet( "df2d.parq" )

# read the files and concatenate
ddf = dd.concat([dd.read_parquet( d ) for d in ["df1d.parq", "df2d.parq"] ], axis=0)

print(ddf.npartitions, ddf.divisions)

我仍然得到預期的 2 個分區,但現在分區是(Timestamp('2000-01-01 00:00:00'), Timestamp('2000-01-02 00:00:00'), Timestamp('2000-01-02 23:00:00'))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM