寄木細工の形式のやや大きい(〜20 GB)パーティション化されたデータセットがあります。 pyarrow
を使用してデータセットから特定のパーティションを読み取りたいと思います。 pyarrow.parquet.ParquetDataset
でこれを達成できると思いましたが、そうではないようです。これは私が欲しいものを説明するための小さな例です。
ランダムなデータセットを作成するには:
from collections import OrderedDict
from itertools import product, chain
from uuid import uuid4
import os
from glob import glob
import numpy as np
import pandas as pd
import pyarrow as pa
from pyarrow.parquet import ParquetWriter, ParquetDataset
def get_partitions(basepath, partitions):
"""Generate directory hierarchy for a paritioned dataset
data
├── part1=foo
│ └── part2=True
├── part1=foo
│ └── part2=False
├── part1=bar
│ └── part2=True
└── part1=bar
└── part2=False
"""
path_tmpl = '/'.join(['{}={}'] * len(partitions)) # part=value
path_tmpl = '{}/{}'.format(basepath, path_tmpl) # part1=val/part2=val
parts = [product([part], vals) for part, vals in partitions.items()]
parts = [i for i in product(*parts)]
return [path_tmpl.format(*Tuple(chain.from_iterable(i))) for i in parts]
partitions = OrderedDict(part1=['foo', 'bar'], part2=[True, False])
parts = get_partitions('data', partitions)
for part in parts:
# 3 columns, 5 rows
data = [pa.array(np.random.Rand(5)) for i in range(3)]
table = pa.Table.from_arrays(data, ['a', 'b', 'c'])
os.makedirs(part, exist_ok=True)
out = ParquetWriter('{}/{}.parquet'.format(part, uuid4()),
table.schema, flavor='spark')
out.write_table(table)
out.close()
パーティション1のすべての値を読み取り、パーティション2の場合はTrueのみを読み取りたいのですが、pandas.read_parquet
を使用すると、それは不可能であり、常に列全体を読み取る必要があります。 pyarrow
で次のことを試しました。
parts2 = OrderedDict(part1=['foo', 'bar'], part2=[True])
parts2 = get_partitions('data', parts2)
files = [glob('{}/*'.format(dirpath)) for dirpath in parts2]
files = [i for i in chain.from_iterable(files)]
df2 = ParquetDataset(files).read().to_pandas()
それも機能しません:
>>> df2.columns
Index(['a', 'b', 'c'], dtype='object')
これはpyspark
で次のように簡単に実行できます。
def get_spark_session_ctx(appName):
"""Get or create a Spark Session, and the underlying Context."""
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName(appName).getOrCreate()
sc = spark.sparkContext
return (spark, sc)
spark, sc = get_spark_session_ctx('test')
spark_df = spark.read.option('basePath', 'data').parquet(*parts2)
df3 = spark_df.toPandas()
以下に示すように:
>>> df3.columns
Index(['a', 'b', 'c', 'part1', 'part2'], dtype='object')
これはpyarrow
またはpandas
で実行できますか、それともカスタム実装が必要ですか?
更新:Wesの要求に応じて、これは現在 [〜#〜] jira [〜#〜] にあります。
質問:pyarrowを使用してパーティション化された寄木細工のデータセットから特定のパーティションを読み取るにはどうすればよいですか?
回答:今はできません。
https://issues.Apache.org/jira でこの機能をリクエストするApache Arrow JIRAを作成できますか?
これはpyarrowAPIでサポートできるはずですが、誰かがそれを実装する必要があります。ありがとうございました
Pyarrowバージョン0.10.0以降、filters
kwargを使用してクエリを実行できます。あなたの場合、それは次のようになります:
import pyarrow.parquet as pq
dataset = pq.ParquetDataset('path-to-your-dataset', filters=[('part2', '=', 'True'),])
table = dataset.read()