在Python

时间:2018-04-23 20:33:27

标签: python pandas amazon-web-services amazon-s3 aws-lambda

我正在寻找关于这个项目的一些建议。我的想法是使用Python和Lambda来聚合数据并响应网站。主要参数是日期范围,可以是动态的。

项目要求:

  • 从存储在JSON中的月度返回文件中读取数据(每个文件包含大约3000个证券,大小为1.6 MB)
  • 将数据汇总到各个存储桶中,显示每个存储桶的计数和回报(就我们的目的而言,这里可以说存储桶是可以变化的扇区和市值范围)
  • 在网站上显示汇总数据

问题我面对 我已经在AWS Lambda中成功实现了这一点,但是在测试20年数据的请求时(是的,我得到它们),我开始在AWS Lambda中达到内存限制。

我使用的流程: 所有文件都存储在S3中,因此我使用boto3库来获取文件,将它们读入内存。这仍然很小,没有任何实际意义。

我使用json.loads将文件转换为pandas数据帧。我正在将所有文件加载到一个大型数据框中。 - 这是内存耗尽的地方。

然后,我使用groupby将数据框传递给自定义聚合,以获得我的结果。这部分并不像我想的那么快,但是能够得到我需要的东西。

最终结果数据帧然后转换回JSON并且小于500 MB。

当它在lambda外部工作时的整个过程大约是40秒 我尝试用线程运行它并同时处理单个帧但性能降低到大约1分30秒。

虽然我宁愿不废弃一切并重新开始,但如果有更有效的方法来解决这个问题,我愿意这样做。旧进程在没有使用lambda的情况下完成了node.js中的所有内容,并且花了将近3分钟来生成。

目前使用的代码 我不得不清理这一点以取出一些项目,但这里是使用的代码。 将数据从S3读入JSON,这将产生一个字符串数据列表。

 while not q.empty():
            fkey = q.get()


            try:
                obj = self.s3.Object(bucket_name=bucket,key=fkey[1])
                json_data = obj.get()['Body'].read().decode('utf-8')

                results[fkey[1]] = json_data
            except Exception as e:
                results[fkey[1]] = str(e)
            q.task_done()

循环访问JSON文件以构建工作的数据框

for k,v in s3Data.items():        
        lstdf.append(buildDataframefromJson(k,v))

def buildDataframefromJson(key, json_data):

    tmpdf = pd.DataFrame(columns=['ticker','totalReturn','isExcluded','marketCapStartUsd',
                                  'category','marketCapBand','peGreaterThanMarket', 'Month','epsUsd']
                         )
     #Read the json into a dataframe
    tmpdf = pd.read_json(json_data,
                         dtype={
                            'ticker':str,
                            'totalReturn':np.float32,
                            'isExcluded':np.bool,
                            'marketCapStartUsd':np.float32,
                            'category':str,
                            'marketCapBand':str,
                            'peGreaterThanMarket':np.bool,
                            'epsUsd':np.float32
                            })[['ticker','totalReturn','isExcluded','marketCapStartUsd','category',
                        'marketCapBand','peGreaterThanMarket','epsUsd']]
    dtTmp = datetime.strptime(key.split('/')[3], "%m-%Y")
    dtTmp = datetime.strptime(str(dtTmp.year) + '-'+ str(dtTmp.month),'%Y-%m')
    tmpdf.insert(0,'Month',dtTmp, allow_duplicates=True)

    return tmpdf

0 个答案:

没有答案