Цикл по строкам из электронной таблицы, запуск функции по каждой строке и вывод результата в конец той же строки
Это сложный вопрос, но я застрял на 2 недели, и я был бы признателен, если бы кто-то мог помочь мне в этом. По сути, у меня есть электронная таблица, в которой первая строка выглядит следующим образом (я не смог вставить электронную таблицу здесь и сохранить ее в понятном виде): A1= Материал, B1= Янв 15, C1= Фев 15, ..., AW=Dec/18. Список материалов (столбец) проходит весь путь от A2 до A6442, и каждая строка имеет номер детали. Начиная с B2:B6442 каждая строка представляет количество для каждой детали. Итак, строка B2:AW2 будет потреблением для детали на B1 с января /15 по декабрь / 18.
Учитывая вышесказанное, я хочу пройтись по каждой отдельной строке, применить def (triple_exponential_smoothing) и вернуть последние 6 чисел из серии обратно в Excel, в ячейках от AR до AW (например, для 2-й строки, AR2:AW2). Я бы использовал первые 3,5 года (B2:AQ2) в качестве базы для расчета на оставшиеся 6 месяцев года (AR2:AW2). Когда я запускаю его с определенным диапазоном (как показано ниже), он работает:
series = xw.Range((2,2),(2, 37)).value
Когда я вместо этого запускаю цикл, я даже не могу получить выходные данные функции, не говоря уже о том, чтобы записать ее обратно в Excel. Мой код ниже приведен ниже:
import os
import xlwings as xw
#Defining folder
os.chdir('G:\...\Reports')
#importing data
wb = xw.Book('sheet.xlsx')
sht = wb.sheets['sheet']
series = [sht.range((i,2),(i, 37)).value for i in range(2, 6443)]
# Holt Winters formula
def initial_trend(series, slen):
sum = 0.0
for i in range(slen):
sum += float(series[i+slen] - series[i]) / slen
return sum / slen
def initial_seasonal_components(series, slen):
seasonals = {}
season_averages = []
n_seasons = int(len(series)/slen)
# compute season averages
for j in range(n_seasons):
season_averages.append(sum(series[slen*j:slen*j+slen])/float(slen))
# compute initial values
for i in range(slen):
sum_of_vals_over_avg = 0.0
for j in range(n_seasons):
sum_of_vals_over_avg += series[slen*j+i]-season_averages[j]
seasonals[i] = sum_of_vals_over_avg/n_seasons
return seasonals
def triple_exponential_smoothing(series, slen, alpha, beta, gamma, n_preds):
result = []
seasonals = initial_seasonal_components(series, slen)
for i in range(len(series)+n_preds):
if i == 0: # initial values
smooth = series[0]
trend = initial_trend(series, slen)
result.append(series[0])
continue
if i >= len(series): # we are forecasting
m = i - len(series) + 1
result.append((smooth + m*trend) + seasonals[i%slen])
else:
val = series[i]
last_smooth, smooth = smooth, alpha*(val-seasonals[i%slen]) + (1-alpha)*(smooth+trend)
trend = beta * (smooth-last_smooth) + (1-beta)*trend
seasonals[i%slen] = gamma*(val-smooth) + (1-gamma)*seasonals[i%slen]
result.append(smooth+trend+seasonals[i%slen])
return result
#printing results for the function looped through all rows
print(triple_exponential_smoothing(series, 12, 0.96970912, 0.07133329, 0, 12))
Я что-то пропустил? Я открыт для других способов сделать это, пока я могу сделать все ряды одновременно.
Спасибо всем заранее.
1 ответ
Самый простой способ сделать это - создать пользовательскую функцию (UDF), работающую в одной строке, затем вы можете скопировать ее по мере необходимости.
Для повышения производительности вы можете прочитать весь диапазон данных в Python, пройтись по каждой строке, записать результаты в список списков или массив Numpy, а затем записать все результаты обратно в диапазон Excel за одну операцию. Это также может быть удобно написано как UDF.