使用pyarrow读取镶木地板文件时如何解码字典列?
How to decode dictionary column when using pyarrow to read parquet files?
我在 s3 存储桶中存储了三个 .snappy.parquet
文件,我尝试使用 pandas.read_parquet()
但它仅在我指定一个镶木地板文件时有效,例如:df = pandas.read_parquet("s3://bucketname/xxx.snappy.parquet")
,但是如果我不指定文件名 df = pandas.read_parquet("s3://bucketname")
,这将不起作用并且它给了我错误:Seek before start of file
.
我看了很多书,然后我发现了这个page
它建议我们可以使用 pyarrow
读取多个 parquet 文件,所以这是我尝试过的:
import s3fs
import import pyarrow.parquet as pq
s3 = s3fs.S3FileSystem()
bucket_uri = f's3://bucketname'
data = pq.ParquetDataset(bucket_uri, filesystem=s3)
df = data.read().to_pandas()
这行得通,但我发现 df
中其中一列的值是一个字典,我如何解码这个字典和选定的 key
作为列名和 value
作为相应的值?
例如当前列:
column_1
{'Id': 'xxxxx', 'name': 'xxxxx','age': 'xxxxx'....}
预期列:
Id age
xxx xxx
xxx xxx
这是 data.read().schema
的输出:
column_0: string
-- field metadata --
PARQUET:field_id: '1'
column_1: struct<Id: string, name: string, age: string,.......>
child 0, Id: string
-- field metadata --
PARQUET:field_id: '3'
child 1, name: string
-- field metadata --
PARQUET:field_id: '7'
child 2, age: string
-- field metadata --
PARQUET:field_id: '8'
...........
...........
您有一个“结构类型”的列,您想要将其展平。为此,请在调用 to_pandas
之前调用 flatten
import pyarrow as pa
COLUMN1_SCHEMA = pa.struct([('Id', pa.string()), ('Name', pa.string()), ('Age', pa.string())])
SCHEMA = pa.schema([("column1", COLUMN1_SCHEMA), ('column2', pa.int32())])
df = pd.DataFrame({
"column1": [("1", "foo", "16"), ("2", "bar", "17"), ],
"column2": [1, 2],
})
pa.Table.from_pandas(df, SCHEMA).to_pandas() # without flatten
| column1 | column2 |
|:----------------------------------------|----------:|
| {'Id': '1', 'Name': 'foo', 'Age': '16'} | 1 |
| {'Id': '2', 'Name': 'bar', 'Age': '17'} | 2 |
pa.Table.from_pandas(df, SCHEMA).flatten().to_pandas() # with flatten
| column1.Id | column1.Name | column1.Age | column2 |
|-------------:|:---------------|--------------:|----------:|
| 1 | foo | 16 | 1 |
| 2 | bar | 17 | 2 |
作为旁注,您不应将其称为 dictionary
专栏。 dictionary
是pyarrow中的加载项,通常指的是distionary encoding
编辑:如何读取 parquet 中的列子集
import pyarrow.parquet as pq
table = pa.Table.from_pandas(df, SCHEMA)
pq.write_table(table, 'data.pq')
# Using read_table:
pq.read_table('data.pq', columns=['column1.Id', 'column1.Age'])
# Using ParquetDataSet:
pq.ParquetDataset('data.pq').read(columns=['column1.Id', 'column1.Age'])
我在 s3 存储桶中存储了三个 .snappy.parquet
文件,我尝试使用 pandas.read_parquet()
但它仅在我指定一个镶木地板文件时有效,例如:df = pandas.read_parquet("s3://bucketname/xxx.snappy.parquet")
,但是如果我不指定文件名 df = pandas.read_parquet("s3://bucketname")
,这将不起作用并且它给了我错误:Seek before start of file
.
我看了很多书,然后我发现了这个page
它建议我们可以使用 pyarrow
读取多个 parquet 文件,所以这是我尝试过的:
import s3fs
import import pyarrow.parquet as pq
s3 = s3fs.S3FileSystem()
bucket_uri = f's3://bucketname'
data = pq.ParquetDataset(bucket_uri, filesystem=s3)
df = data.read().to_pandas()
这行得通,但我发现 df
中其中一列的值是一个字典,我如何解码这个字典和选定的 key
作为列名和 value
作为相应的值?
例如当前列:
column_1
{'Id': 'xxxxx', 'name': 'xxxxx','age': 'xxxxx'....}
预期列:
Id age
xxx xxx
xxx xxx
这是 data.read().schema
的输出:
column_0: string
-- field metadata --
PARQUET:field_id: '1'
column_1: struct<Id: string, name: string, age: string,.......>
child 0, Id: string
-- field metadata --
PARQUET:field_id: '3'
child 1, name: string
-- field metadata --
PARQUET:field_id: '7'
child 2, age: string
-- field metadata --
PARQUET:field_id: '8'
...........
...........
您有一个“结构类型”的列,您想要将其展平。为此,请在调用 to_pandas
import pyarrow as pa
COLUMN1_SCHEMA = pa.struct([('Id', pa.string()), ('Name', pa.string()), ('Age', pa.string())])
SCHEMA = pa.schema([("column1", COLUMN1_SCHEMA), ('column2', pa.int32())])
df = pd.DataFrame({
"column1": [("1", "foo", "16"), ("2", "bar", "17"), ],
"column2": [1, 2],
})
pa.Table.from_pandas(df, SCHEMA).to_pandas() # without flatten
| column1 | column2 |
|:----------------------------------------|----------:|
| {'Id': '1', 'Name': 'foo', 'Age': '16'} | 1 |
| {'Id': '2', 'Name': 'bar', 'Age': '17'} | 2 |
pa.Table.from_pandas(df, SCHEMA).flatten().to_pandas() # with flatten
| column1.Id | column1.Name | column1.Age | column2 |
|-------------:|:---------------|--------------:|----------:|
| 1 | foo | 16 | 1 |
| 2 | bar | 17 | 2 |
作为旁注,您不应将其称为 dictionary
专栏。 dictionary
是pyarrow中的加载项,通常指的是distionary encoding
编辑:如何读取 parquet 中的列子集
import pyarrow.parquet as pq
table = pa.Table.from_pandas(df, SCHEMA)
pq.write_table(table, 'data.pq')
# Using read_table:
pq.read_table('data.pq', columns=['column1.Id', 'column1.Age'])
# Using ParquetDataSet:
pq.ParquetDataset('data.pq').read(columns=['column1.Id', 'column1.Age'])