问题
如何使用Dask Distributed将文件目录并行读取到各个DataFrame中,然后使用自定义函数对其进行处理?假设n个文件大约是100,000
背景
我是Dask的新手,也不怎么问这个问题(要使用哪些术语,等等),所以这是我要完成的工作的图片:
我有很多存储在HDFS中的小型.txt单独的“分类帐”文件(例如,带有时间戳的行分隔文件和时间戳的属性值)。
同时,我想...
将每个文件读入一个DataFrame中(注释:我不尝试将所有文件组合成一个大df!);
对每个DataFrame应用自定义函数(请参见下文);然后
将每个结果(从自定义函数返回)合并到最终对象中,并将其保存回HDFS。
似乎(当使用Google搜索相关术语时)我发现的几乎所有答案都是关于将多个文件加载到单个数据框中的。
我正在处理的是我正在使用的功能
每个分类帐文件/数据框:
+---------+------+-------------------+-----+
| 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
这样,分类帐数据/ DataFrame会减少为(假设计算是在2019-04-14进行的):
{ '_id': 'ledger-filename', 'location': 'ICEXCEPT', 'days_in_location': 4, 'status': 'X', 'days_in_status': 3, 'wh_id': 20 }
答案 0 :(得分:0)
实际上不可能从多个进程并行写入一个输出文件,因为您不知道每个结果会预先存储多长时间,因此您也不知道文件中将其他结果放置在何处。而且,HDFS确实喜欢接收大块连续数据,而不是增量更新(也许是64MB)。
您可以做几件事:
client.submit
API和as_completed
将结果从主进程写入输出文件。请注意,如果这很重要,您可以使遵守原始顺序,但是这将需要一些额外的工作。