PySpark和Pandas - 从S3中读取分区的csv文件,跳过空的

时间:2018-02-07 06:26:59

标签: apache-spark amazon-s3 pyspark boto3 emr

使用PySpark,我有一些代码可以运行一堆查询。

for index, query in enumerate(query_map):  
  spark_dataframe.filter(
       query).write.csv('s3://OutputBucket/Csvs/Query_{}'.format(index)

我是新手,但我明白每个分区都会将单个csv文件写入名为Query_[index]的目录。现在我想收集这些文件并将它们放入pandas数据框中。

import boto3
import pandas
s3 = boto3.resource('s3')
my_bucket = s3.Bucket("OutputBucket")
#Get all csv names
csvs = [
    "s3://OutputBucket/Csvs/"+\
    str(i.key) for i in my_bucket.objects.filter(Prefix='Query/')] 
to_concat = []
#Turn them into a dataframe
for csv in csvs:
    try:
        to_put_in.append(pandas.read_csv(csv))
    except pandas.errors.EmptyDataError:
        pass
#Join dataframe
my_big_dataframe = pandas.concat(to_concat)

问题是Pyspark写了很多空文件。所以我的代码花了很多时间尝试读取一个空的csv文件只是为了抛出一个异常。

据我所知,df_spark.toPandas()函数违背了spark的目的,因为它将它放入驱动程序内存并且不使用每个分区的IO并行化。它也违背了使用coalesce的火花的目的。所以写一堆csv然后手动读取它们并不是一个糟糕的主意。

TL;博士

我的问题是,是否有办法跳过那些由pyspark写入的空csv文件:

  1. 也许boto3可以先按大小排序,然后迭代直到我们罚款并清空文件?

  2. PySpark有没有办法在没有击败pyspark的情况下做到这一点?

1 个答案:

答案 0 :(得分:0)

几个月前我遇到了类似的问题。使用类似这样的东西

# get the number of non-empty partitions in dataframe df
numNonEmptyPartitions = (df.rdd.glom().map(lambda x: 1 if len(x)>0 else 0).
                                reduce(lambda x,y: x+y))

df = df.coalesce(numNonEmptyPartitions)

现在,您将拥有所有非空分区。

相关问题