我正在使用Dask读取由PySpark生成的Parquet文件,其中一列是字典列表(即array<map<string,string>>'
)。 df的示例为:
import pandas as pd
df = pd.DataFrame.from_records([
(1, [{'job_id': 1, 'started': '2019-07-04'}, {'job_id': 2, 'started': '2019-05-04'}], 100),
(5, [{'job_id': 3, 'started': '2015-06-04'}, {'job_id': 9, 'started': '2019-02-02'}], 540)],
columns=['uid', 'job_history', 'latency']
)
使用engine='fastparquet
时,Dask可以很好地读取所有其他列,但是对于复杂类型的列,返回None
s列。设置engine='pyarrow'
时,出现以下异常:
ArrowNotImplementedError: lists with structs are not supported.
许多谷歌搜索已经明确表明,目前尚不真正支持使用嵌套数组读取列,而且我也不完全确定处理此问题的最佳方法是什么。我认为我的选择是:
json
库来解析列。模式很简单,并且在可能的情况下会完成工作list
将数据分解为几列,并注意这些列中的数据通过索引相互关联/映射(例如idx {中的元素这些键/列中的{1}}均来自同一来源)。这行得通,但坦率地说,让我伤心了:(我很想听听其他人如何绕过这个限制。我的公司经常在他们的parquest中使用嵌套数组,因此,我讨厌不得不放弃使用Dask。
答案 0 :(得分:0)
公平地说,熊猫并不能很好地支持非简单类型(当前)。可能是pyarrow会不转换为大熊猫,而将来,大熊猫会直接使用这些箭头结构。
事实上,我认为最直接的方法是将列重写为B / JSON编码的文本,然后使用fastparquet进行加载,并指定使用B / JSON进行加载。您应该在该列中获得字典列表,但是性能会很慢。
请注意,旧项目oamap及其后继项目awkward提供了一种使用python语法在嵌套列表/地图/结构树上进行迭代和聚合的方法,但是使用Numba进行了编译,因此您永远不需要实例化中间python对象。它们不是为实木复合地板而设计的,而是具有实木复合地板的兼容性,因此可能对您很有用。
答案 1 :(得分:0)
当我尝试使用熊猫阅读时,我正在与pyarrow.lib.ArrowNotImplementedError: Reading lists of structs from Parquet files not yet supported
交流;但是,当我使用pyspark阅读并转换为熊猫时,数据至少会加载:
import pyspark
spark = pyspark.sql.SparkSession.builder.getOrCreate()
df = spark.read.load(path)
pdf = df.toPandas()
,并且令人讨厌的字段现在呈现为pyspark Row对象,该对象具有一些结构化的解析,但是您可能必须编写自定义的熊猫函数才能从其中提取数据:
>>> pdf["user"][0]["sessions"][0]["views"]
[Row(is_search=True, price=None, search_string='ABC', segment='listing', time=1571250719.393951), Row(is_search=True, price=None, search_string='ZYX', segment='homepage', time=1571250791.588197), Row(is_search=True, price=None, search_string='XYZ', segment='listing', time=1571250824.106184)]
单个记录可以呈现为字典,只需在所需的Row对象上调用.asDict(recursive=True)
。
不幸的是,启动SparkSession上下文大约需要5秒钟,并且每个spark操作还比pandas操作(对于中小型数据集)要花费更长的时间,因此我非常希望使用更多的python-native选项