2016-10-19 5 views
2

Я пытаюсь использовать Python для записи данных из открытого набора данных SPSS в файл excel. Приведенная ниже программа работает нормально, но для файла с 1,4 миллионами точек данных требуется около 35 секунд (2500 случаев, 700 переменных).Эффективно записывать данные SPSS в Excel с помощью Python

На данный момент я просматриваю каждый случай (как кортеж), а затем назначая каждый элемент кортежа в ячейку. openpyxl - это предпочтительный модуль Excel (поскольку раньше я не использовал какой-либо другой).

Я собираюсь использовать программу Python для гораздо больших наборов данных, поэтому мне было интересно, есть ли более эффективная логика этого.

BEGIN PROGRAM. 

import spssdata 
import spss,spssaux, sys 
import openpyxl 
from openpyxl import Workbook 
import gc 

#initialise timer 
time_start = time.time() 

#Create the workbook to save the codebook 
wb=openpyxl.Workbook() 
ws1=wb.create_sheet() 

spss.StartDataStep() 
MyFile = spss.Dataset() 
varDict = spssaux.VariableDict() 
MyCases=MyFile.cases 
MyVars=MyFile.varlist 

for varnum, varname in enumerate(MyFile.varlist): 
     ws1.cell(row=1,column=varnum+1).value=varname.name 
     ws2.cell(row=1,column=varnum+1).value=varname.name 

for eachcase in range (len(MyCases)): 
    for eachvar in range (len(MyCases[eachcase])): 
     ValueToWrite=MyCases[eachcase][eachvar] 
     ws1.cell(row=eachcase+2,column=eachvar+1).value=ValueToWrite 

spss.EndDataStep() 

wb.save("some filename") 
del wb 
gc.collect() 
time_end = time.time() 
time_taken = int(time_end-time_start) 
print ("Saving took " + str(time_taken) + " seconds.") 
END PROGRAM. 
+0

Есть ли особая причина, по которой вы хотите управлять этим экспортом с помощью Python? Как мне кажется, прямой экспорт прямоугольного набора данных в Excel? Почему бы просто не использовать собственный SPSS для сохранения набора данных в виде Excel? В чем причина того, что это нужно использовать в Python? –

+0

Вы правы, это в основном экспорт данных из набора данных. Но я также делаю некоторые преобразования, форматирование, написание частей данных на несколько файлов wroksheets, и все уже написано в Python. Я планирую сделать это расширением SPSS. Сохранение, казалось, было легкой частью, но оказалось довольно трудоемким. –

+0

Я использовал/использовал 'xlsxwriter', который имеет метод' set_column', поэтому избегает необходимости цикла для каждой строки/случая для заполнения файла Excel. Он также имеет различные другие функции для форматирования ect. –

ответ

1

Вы можете поэкспериментировать с использованием подхода win32com. Обычно это довольно медленно, но у него есть то преимущество, что он может выполнять большую часть передачи данных за один раз. Вам просто нужно будет подготовить свои данные в подходящем размере список:

import win32com.client as win32 

data = [["A", "B"] for _ in range(10000)] 

excel = win32.gencache.EnsureDispatch('Excel.Application') 
excel.DisplayAlerts = False 
wb = excel.Workbooks.Add() 
ws = wb.Worksheets.Add() 
ws.Range(ws.Cells(1, 1), ws.Cells(len(data), 2)).Value = data 
wb.SaveAs(r'c:\python\test.xlsx') 
excel.Application.Quit() 

Timing это с range(1000000) занял около 7,5 секунд.

AFAIK в Oнет возможности писать более одной ячейки за раз.


на основе существующего кода, я хотел бы предложить что-то вдоль линий:

import win32com.client as win32 
import time 
import spss,spssaux, sys 

#initialise timer 
time_start = time.time() 

spss.StartDataStep() 
MyFile = spss.Dataset() 
MyCases = MyFile.cases 
spss.EndDataStep() 

excel = win32.gencache.EnsureDispatch('Excel.Application') 
excel.DisplayAlerts = False 

wb = excel.Workbooks.Add() 
ws1 = wb.Worksheets("Sheet1") 
ws2 = wb.Worksheets("Sheet2") 

# Add header to both sheets 
ws1.Range(ws1.Cells(1, 1), ws1.Cells(1, len(MyFile.varlist))).Value = MyFile.varlist 
ws2.Range(ws2.Cells(1, 1), ws2.Cells(1, len(MyFile.varlist))).Value = MyFile.varlist 

# Copy data 
ws1.Range(ws1.Cells(2, 1), ws1.Cells(1 + len(MyCases), len(MyCases[0]))).Value = MyCases 

wb.SaveAs(r'e:\python temp\test.xlsx') 
excel.Application.Quit() 

print("Saving took {:.1f} seconds.".format(time.time() - time_start)) 
+0

Хотя все это делается, оно все еще очень медленное. Это заняло около 10% меньше времени на моей машине, но это не значительная эффективность, которую я ищу при работе с миллионами точек данных. –

+0

Вы приурочили 'spss.Dataset()'? Я предполагаю, что эта часть пренебрежимо мала. –

+0

Если я вырезал вложенные петли в моем исходном коде, остальное занимает от 2 до 5 секунд (в зависимости от доступных ресурсов машины) –

0

Убедитесь LXML установлен и использовать режим записи только openpyxl, в предположении, что вы можете работать на row- . Если это невозможно напрямую, вам понадобится какая-то промежуточная структура, которая может дать вам строки.

0

В общем, класс spss.Cursor (или spssdata.Spssdata) намного быстрее, чем класс spss.Dataset, и для этого приложения вам не нужны дополнительные функции класса Dataset. Хотя скорость набора Dataset в основном возникает при написании статистики, класс Cursor, вероятно, будет быстрее.

Смежные вопросы