Python Dask分布式:并行读取和分析大量单个文件
问题 如何使用Dask Distributed将文件目录并行读取到单个数据帧中,然后使用自定义函数处理这些数据帧?假设n个文件大约是100000个 背景 我是Dask的新手,不太知道如何问这个问题(使用哪些术语等),所以这里有一张我试图完成的图片: 我在HDFS中存储了许多小的、单独的.txt“分类账”文件(例如,带有时间戳的行分隔文件和时间戳时的属性值) 同时,我想Python Dask分布式:并行读取和分析大量单个文件,python,dask,dask-distributed,pyarrow,Python,Dask,Dask Distributed,Pyarrow,问题 如何使用Dask Distributed将文件目录并行读取到单个数据帧中,然后使用自定义函数处理这些数据帧?假设n个文件大约是100000个 背景 我是Dask的新手,不太知道如何问这个问题(使用哪些术语等),所以这里有一张我试图完成的图片: 我在HDFS中存储了许多小的、单独的.txt“分类账”文件(例如,带有时间戳的行分隔文件和时间戳时的属性值) 同时,我想 将每个文件读入一个数据帧(注意:我不想把所有文件合并成一个大df!) 对每个数据帧应用自定义函数(见下文);然后 将每个结果(
+---------+------+-------------------+-----+
| location|status| timestamp|wh_id|
+---------+------+-------------------+-----+
| PUTAWAY| I|2019-04-01 03:14:00| 20|
|PICKABLE1| X|2019-04-01 04:24:00| 20|
|PICKABLE2| X|2019-04-01 05:33:00| 20|
|PICKABLE2| A|2019-04-01 06:42:00| 20|
| HOTPICK| A|2019-04-10 05:51:00| 20|
| ICEXCEPT| A|2019-04-10 07:04:00| 20|
| ICEXCEPT| X|2019-04-11 09:28:00| 20|
+---------+------+-------------------+-----+
分析功能:
from dateutil.relativedelta import relativedelta
from datetime import datetime
from pyspark.sql.functions import to_timestamp
def analyze(df):
columns_with_age = ("location", "status")
columns_without_age = ("wh_id")
# Get the most-recent values (from the last row of the df)
row_count = df.count()
last_row = df.collect()[row_count-1]
# Create an empty "final row" dictionary
final_row = {}
# For each column for which we want to calculate an age value ...
for c in columns_with_age:
# Initialize loop values
target_value = last_row.__getitem__(c)
final_row[c] = target_value
timestamp_at_lookback = last_row.__getitem__("timestamp")
look_back = 1
different = False
while not different:
previous_row = df.collect()[row_count - 1 - look_back]
if previous_row.__getitem__(c) == target_value:
timestamp_at_lookback = previous_row.__getitem__("timestamp")
look_back += 1
else:
different = True
# At this point, a difference has been found, so calculate the age
final_row["days_in_{}".format(c)] = relativedelta(datetime.now(), timestamp_at_lookback).days
因此,分类账数据/数据框架将减少到(假设计算在2019-04-14运行):
从多个进程并行写入单个输出文件实际上是不可能的,因为您不知道每个结果将提前多长时间,所以您不知道在文件中放置其他结果的位置。此外,HDFS确实喜欢接收大块连续数据,而不是增量更新(可能是64MB) 你可以做几件事:
- 将所有输出写入单独的文件,然后运行单独的作业来连接它们;如果数据帧的处理比读/写时间要长,那么这是一件非常好的事情
- 使用分布式
客户端。提交
API和
将结果从主进程写入输出文件。请注意,如果这很重要,您可以将这方面作为原始订单,但这需要一些额外的工作完成后
的信息。看看这个。看起来我可能想混合上面的两个注释——也就是说,将文件读取/评估合并到一个函数中,然后使用Dask Distributed的client.map(eval_func,[HDFS文件路径列表])
。
{ '_id': 'ledger-filename', 'location': 'ICEXCEPT', 'days_in_location': 4, 'status': 'X', 'days_in_status': 3, 'wh_id': 20 }