Python中的I / O效率

时间:2015-04-28 06:30:19

标签: python io

我正在编写一个程序:

  • 从每行的Excel工作表中读取内容(总共90,000行)
  • 将内容与每行的另一张excel表(总共600,000行)进行比较
  • 如果匹配,请将匹配条目写入新的Excel工作表

我写过脚本,一切正常。然而,计算时间是巨大的。一小时后,它从第一张纸上只完成了200行,从而编写了200个不同的文件。

我想知道是否有办法以不同的方式保存匹配,因为我稍后会使用它们?有什么方法可以保存在矩阵中吗?

import xlrd
import xlsxwriter
import os, itertools
from datetime import datetime
# choose the incident excel sheet
book_1 = xlrd.open_workbook('D:/Users/d774911/Desktop/Telstra Internship/Working files/Incidents.xlsx')
# choose the trap excel sheet
book_2 = xlrd.open_workbook("D:/Users/d774911/Desktop/Telstra Internship/Working files/Traps.xlsx")
# choose the features sheet
book_3 = xlrd.open_workbook("D:/Users/d774911/Desktop/Telstra Internship/Working files/Features.xlsx")
# select the working sheet, either by name or by index
Traps = book_2.sheet_by_name('Sheet1')
# select the working sheet, either by name or by index
Incidents = book_1.sheet_by_name('Sheet1')
# select the working sheet, either by name or by index
Features_Numbers = book_3.sheet_by_name('Sheet1')
#return the total number of rows for the traps sheet
Total_Number_of_Rows_Traps = Traps.nrows
# return the total number of rows for the incident sheet
Total_Number_of_Rows_Incidents = Incidents.nrows
# open a file two write down the non matching incident's numbers
print(Total_Number_of_Rows_Traps, Total_Number_of_Rows_Incidents)
write_no_matching =   open('C:/Users/d774911/PycharmProjects/GlobalData/No_Matching.txt', 'w')

# For loop to iterate for all the row for the incident sheet
for Rows_Incidents in range(Total_Number_of_Rows_Incidents):
    # Store content for the comparable cell for incident sheet
    Incidents_Content_Affected_resources = Incidents.cell_value(Rows_Incidents, 47)
    # Store content for the comparable cell for incident sheet
    Incidents_Content_Product_Type = Incidents.cell_value(Rows_Incidents, 29)
    # Convert Excel date type into python type
    Incidents_Content_Date = xlrd.xldate_as_tuple(Incidents.cell_value(Rows_Incidents, 2), book_1.datemode)
    # extract the year, month and day
    Incidents_Content_Date = str(Incidents_Content_Date[0]) + ' ' + str(Incidents_Content_Date[1]) + ' ' + str(Incidents_Content_Date[2])
    # Store content for the comparable cell for incident sheet
    Incidents_Content_Date = datetime.strptime(Incidents_Content_Date, '%Y %m %d')
    # extract the incident number
    Incident_Name = Incidents.cell_value(Rows_Incidents, 0)
    # Create a workbook for the selected incident
    Incident_Name_Book = xlsxwriter.Workbook(os.path.join('C:/Users/d774911/PycharmProjects/GlobalData/Test/', Incident_Name + '.xlsx'))
    # Create sheet name for the created workbook
    Incident_Name_Sheet = Incident_Name_Book.add_worksheet('Sheet1')
    # insert the first row that contains the features
    Incident_Name_Sheet.write_row(0, 0, Features_Numbers.row_values(0))
    Insert_Row_to_Incident_Sheet = 0

# For loop to iterate for all the row for the traps sheet
for Rows_Traps in range(Total_Number_of_Rows_Traps):

    # Store content for the comparable cell for traps sheet
    Traps_Content_Node_Name = Traps.cell_value(Rows_Traps, 3)
    # Store content for the comparable cell for traps sheet
    Traps_Content_Event_Type = Traps.cell_value(Rows_Traps, 6)
    # extract date temporally
    Traps_Content_Date_temp = Traps.cell_value(Rows_Traps, 10)
    # Store content for the comparable cell for traps sheet
    Traps_Content_Date = datetime.strptime(Traps_Content_Date_temp[0:10], '%Y-%m-%d')

    # If the content matches partially or full
    if len(str(Traps_Content_Node_Name)) * len(str(Incidents_Content_Affected_resources)) != 0 and \
            str(Incidents_Content_Affected_resources).lower().find(str(Traps_Content_Node_Name).lower()) != -1 and \
            len(str(Traps_Content_Event_Type)) * len(str(Incidents_Content_Product_Type)) != 0 and \
            str(Incidents_Content_Product_Type).lower().find(str(Traps_Content_Event_Type).lower()) != -1 and \
            len(str(Traps_Content_Date)) * len(str(Incidents_Content_Date)) != 0 and \
            Traps_Content_Date <= Incidents_Content_Date:
        # counter for writing inside the new incident sheet
        Insert_Row_to_Incident_Sheet = Insert_Row_to_Incident_Sheet + 1
        # Write the Incident information
        Incident_Name_Sheet.write_row(Insert_Row_to_Incident_Sheet, 0, Incidents.row_values(Rows_Incidents))
        # Write the Traps information
        Incident_Name_Sheet.write_row(Insert_Row_to_Incident_Sheet, 107, Traps.row_values(Rows_Traps))

Incident_Name_Book.close()

由于

3 个答案:

答案 0 :(得分:3)

您正在为每个单元格寻找/读取一小部分数据。这是非常低效的。

尝试将所有信息一次性读入基本的敏感python数据结构(列表,序列等),并在内存中对此数据集进行比较/操作,并一次性写入所有结果。如果并非所有数据都适合内存,请尝试将其划分为子任务。

必须读取数据集10次,每次提取十分之一数据可能仍然比独立读取每个单元格快得多。

答案 1 :(得分:3)

我看不出你的代码是如何工作的;第二个循环适用于第一个循环中每一行的变量,但第二个循环不在第一个循环中。

也就是说,以这种方式比较文件的复杂度为O(N * M),这意味着运行时会快速爆炸。在你的情况下,你试图执行54'000'000'000(54亿)循环。

如果遇到这些问题,解决方案始终是一个三步过程:

  1. 转换数据以便于处理
  2. 将数据放入有效的结构(排序列表,dict
  3. 使用高效结构搜索数据
  4. 你必须找到摆脱find()的方法。尝试摆脱要比较的单元格中的所有垃圾,以便使用=。如果有这个,您可以将行放入dict以查找匹配项。或者您可以将其加载到SQL数据库并使用SQL查询(不要忘记添加索引!)

    最后一招是使用排序列表。如果您可以以相同的方式对数据进行排序,那么您可以使用两个列表:

    1. 将两张表中的数据分类为两个列表
    2. 使用两个行计数器(每个列表一个)
    3. 如果第一个列表中的当前项目 less 比第二个列表中的当前项目更少,则没有匹配项,您必须提前第一个行计数器
    4. 如果第一个列表中的当前项目更大比第二个列表中的当前项目更大,那么就没有匹配,您必须提前第二个行计数器
    5. 如果项目相同,则匹配。处理匹配并推进两个计数器。
    6. 这使您可以一次性处理所有项目。

答案 2 :(得分:1)

我建议您使用pandas。该模块提供了大量的功能来比较数据集。它还具有非常快速的excel文件导入/导出算法。

恕我直言,你应该使用merge函数并提供参数how = 'inner'on = [list of your columns to compare]。这将创建一个新数据集,其中只有两个表中出现的行(在定义的列中具有相同的值)。您可以将此新数据集导出到Excel文件中。