[英]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 非常快
更好的方法是單獨讀取 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.