优化pandas计算

2024-04-18 19:03:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我有2200万行房产销售数据在一个名为sale\u transactions的数据库表中。我正在执行一项工作,从该表中读取信息,执行一些计算,并使用结果创建新表的条目。过程如下:

for index, row in zipcodes.iterrows(): # ~100k zipcodes
    sql_string = """SELECT * from sale_transactions WHERE zipcode = '{ZIPCODE}' """
    sql_query = sql_string.format(ZIPCODE=row['zipcode'])         
    df = pd.read_sql(sql_query, _engine)
    area_stat = create_area_stats(df) # function does calculations
    area_stat.save() # saves a Django model

目前,在我的macbookpro(16gbram)上,这个循环的每次迭代大约需要20秒,这意味着代码需要几周才能完成。昂贵的部分是read_sql行。在

我如何优化这一点?我无法将整个sale\u transactions表读入内存,它大约是5gb,因此每次都使用sql查询来捕获带有WHERE子句的相关行。在

大多数关于优化pandas的答案都是使用分块进行阅读的,但是在这种情况下,我需要对所有合并的数据执行WHERE操作,因为我是在create_area_stats函数中进行计算,比如十年内的销售额。除非我开始带着EC2进城,否则我很难访问一台装有RAM的机器,我担心这会很昂贵,而且会带来很多麻烦。在

如有建议,将不胜感激。在


Tags: 数据dfreadsqlstringareasalewhere
2条回答

由于操作中的瓶颈是sqlwhere查询,所以解决方案是索引WHERE语句正在操作的列(即zipcode列)。在

在MySQL中,执行此操作的命令是:

ALTER TABLE `db_name`.`table` 
ADD INDEX `zipcode_index` USING BTREE (`zipcode` ASC);

在进行此更改后,循环执行速度提高了8倍。在

我发现this article很有用,因为它鼓励使用EXPLAIN分析查询,并观察key和{}值为{}时的列索引机会

我也遇到了类似的问题,下面的代码帮助我有效地读取数据库(大约4000万行)。在

offsetID = 0
totalrow = 0



while (True):

    df_Batch=pd.read_sql_query('set work_mem="1024MB"; SELECT * FROM '+tableName+' WHERE row_number > '+ str(offsetID) +' ORDER BY row_number LIMIT 100000' ,con=engine)
    offsetID = offsetID + len(df_Batch)

    #your operation

    totalrow = totalrow + len(df_Batch) 

必须在表中创建一个名为row_number的索引。所以这段代码将按索引方式读取表(100000行)。例如,当您想从200000到210000读取行时,不需要从0读取到210000。它将直接按索引读取。所以它会提高你的表现。在

相关问题 更多 >