Форум сайта python.su
Я в python'e не силен, так как только не давно его изучаю. Нужна Ваша помоoь по оптимизации кода, так каr моя программа считает около 11 минут, а по хорошему должна около 1-2 минут. Принимаю все возможные варианты, и очень прошу Вас помочь пожалуйста! Заранее спасибо.
from itertools import groupby from collections import Counter import sqlite3 db = sqlite3.connect("D:\providers.db") #---------------------------------Все записи----------------------------------- cursor1 = db.cursor() cursor1.execute("SELECT provider, geography FROM incomes") #------------------------------------------------------------------------------ print("Выполняется составление транзакций, подождите...") #--------------------------------ТРАНЗАКЦИИ------------------------------------ def CompilationTransaction(): database = cursor1.fetchall() result = list() for i, j in groupby(sorted(database, key = lambda x: x[0]), lambda x: x[0]): result.append(list(j)) return result def CompilationTransactionGeography(): result = list() for ElemTrans in CompilationTransaction(): result.append(list(map(lambda x: x[1], ElemTrans))) return result #------------------------------------------------------------------------------ class Occurrences: def __init__ (self, Clusters, Transaction): self.C = Clusters self.t = Transaction #--------------Вхождение некоторого объекта в кластер(Вариант 2)--------------- def Occ(self): ind = 0 for ElemC in self.C: if ElemC.count(self.t): ind = (self.C).index(ElemC) break self.resO = ind #------------------------------------------------------------------------------ class SizeOrWidthCluster: def __init__ (self, Cluster): self.C = Cluster #-------------------------------Размер кластера-------------------------------- def SizeC(self): var = 0 for ElemC in self.C: var += len(ElemC) self.resS = var #-----Подсчет уникальных элементов в заданном кластере(Ширина кластера)-------- def WidthC(self): var = 0 j = 0 for ElemC in self.C: var = Counter(ElemC) j += len(var.keys()) self.resW = j #------------------------------------------------------------------------------ class TransactionAddOrRemov: def __init__(self, Clusters, Transaction, r): self.C = Clusters self.t = Transaction self.r = r #-----------------------------Добавление транзакции---------------------------- def TransactionAdd(self): k = 0 S = SizeOrWidthCluster(self.C) #размер кластера S.SizeC() N = len(self.C) #Количество транзакций в кластере W = SizeOrWidthCluster(self.C) #Количество уникальных элементов География(Ширина кластера) W.WidthC() Snew = S.resS + len(self.t) Nnew = N + 1 Wnew = W.resW for ElemC in self.C: k += len(list(set(self.t) & set(ElemC))) if (len(self.t) >= k): Wnew = Wnew + (len(self.t) - k) self.Tadd = (Snew * Nnew / (Wnew ** self.r)) - (S.resS * N / (W.resW ** self.r)) #-----------------------------Удаление транзакции------------------------------ def TransactionRemov(self): k = 0 l = 0 S = SizeOrWidthCluster(self.C) #размер кластера S.SizeC() N = len(self.C) #Количество транзакций в кластере W = SizeOrWidthCluster(self.C) #Количество уникальных элементов География(Ширина кластера) W.WidthC() Snew = S.resS - len(self.t) Nnew = N - 1 Wnew = W.resW if (len(self.C) <= 1): self.Trem = -(S.resS * N / (W.resW ** self.r)) else: for ElemC in self.C: if (ElemC != self.t): k += len(list(set(self.t) & set(ElemC))) l += 1 if (len(self.t) >= k) and (l != 0): Wnew = Wnew - (len(self.t) - k) self.Trem = (Snew * Nnew / (Wnew ** self.r)) - (S.resS * N / (W.resW ** self.r)) class Clope: def __init__ (self, Clusters, Transactions, r): self.C = Clusters self.t = Transactions self.r = r def Algoritm(self): #-----------------------------ЧАСТЬ 1 - ИНИЦИАЛИЗАЦИЯ-------------------------- AddSpisok = list() TransactionCopy = list() TransactionCopy = self.t.copy() AddSpisok.append(TransactionCopy[0]) #Добавляем 1-ую транзакцию в не основной, пустой кластер (self.C).append(list(AddSpisok)) #Добавляем не основной(не пустой) кластер в основной кластер TransactionCopy.pop(0) for ElemTC in TransactionCopy: #Пробегаем по всем транзакциям max_TC = 0 AddSpisok.clear() for ElemC in self.C: #Пробегаем по всем класерам из мн-ва С tadd = TransactionAddOrRemov(ElemC, ElemTC, self.r) tadd.TransactionAdd() if (tadd.Tadd > float(max_TC)): max_TC = tadd.Tadd NC = (self.C).index(ElemC) if max_TC == 0: AddSpisok.append(ElemTC) (self.C).append(list(AddSpisok)) else: self.C[NC].append(ElemTC) f = open('Otchet1.txt', 'w') for ElemC in self.C: f.write(str(len(ElemC))+'\n') f.write(str(ElemC)+'\n'+'\n') f.close() #-------------------------------ЧАСТЬ 2 - ИТЕРАЦИИ----------------------------- print("-> Выполнена первая часть алгоритма: ИНИЦИАЛИЗАЦИЯ!") for ElemT in self.t: max_T = 0 ent_T = Occurrences(self.C, ElemT) #Индекс кластера, в кот. лежит данная транзакция ent_T.Occ() tr = TransactionAddOrRemov(self.C[ent_T.resO], ElemT, self.r) tr.TransactionRemov() for ElemC in self.C: tadd = TransactionAddOrRemov(ElemC, ElemT, self.r) tadd.TransactionAdd() if (ElemC != self.C[ent_T.resO]) and (tadd.Tadd + tr.Trem > float(max_T)): max_T = tadd.Tadd + tr.Trem NC = (self.C).index(ElemC) if max_T > 0: self.C[NC].append(ElemT) for ElemCent in self.C[ent_T.resO]: if ElemCent == ElemT: self.C[ent_T.resO].pop(self.C[ent_T.resO].index(ElemCent)) break if len(self.C[ent_T.resO]) == 0: self.C.pop(self.C.index(self.C[ent_T.resO])) #удалить пустой кластер #------------------------------------------------------------------------------ def main(): Cluster = list() Transactions = list() Transactions = CompilationTransactionGeography() r = int(input("Введите коэффициент отталкивания (целое число) r > 1: ")) print("Производятся вычисления, подождите...") res = Clope(Cluster, Transactions, r) res.Algoritm() f = open('Otchet2.txt', 'w') for ElemC in Cluster: f.write(str(len(ElemC))+'\n') f.write(str(ElemC)+'\n'+'\n') f.close() print("Вычисления окончены!") return res main() db.close()
Офлайн
в sqlite есть сортировки, лучше их применяйте
http://zametkinapolyah.ru/zametki-o-mysql/chast-12-5-sortirovka-vyborki-dannyx-v-bazax-dannyx-order-by-i-select-v-sqlite.html
если обьем выборки велик, лучше работать с записями последовательно
db = sqlite.connect('test.db') c = db.cursor() c.execute('select * from users') while True: data = c.fetchone() if not data: break print data #тут действия с записью db.close()
Отредактировано vic57 (Март 26, 2017 17:53:05)
Офлайн
Попробую, спасибо! Еще какие варианты, предлагайте, все во внимание возьму!
Офлайн
чтобы дать конкретный совет надо видеть структуру данных
можно в csv файл перегнать, с ним работа быстрее чем с БД
db = sqlite.connect('test.db') c = db.cursor() c.execute('select * from users') f = open('data.csv','w') while True: data = c.fetchone() if not data: break l = [unicode(i) for i in data] f.write(';'.join(l).encode('utf-8') + '\n') #формат Excel db.close() f.close()
Офлайн
Student777
сначала сделай профайлинг, потом оптимизируй
Офлайн
Что такое профайлинг? и как это сделать?
Офлайн
Student777В программу запускаешь код, и она измеряет, сколько времени каждая строка выполняется. Профилировщики эти программы называются.
Что такое профайлинг?
Офлайн
Есть несколько вопросов и утверждений:
1) Какую библиотеку нужно подключить, чтобы заработал unicode?
2) Я понял, что мою программу замедляют двойные циклы в Часть1 и Часть2, так как они обращаются в функции, где еще один цикл, и того, если в нашей базе 50000 записей, будет очень долго считать циклы! Помогите, как избавиться от циклов, какими функциями или методам?(Если можно с примером)
И еще, до этого, где у меня считаются транзакции сначала тоже был двойной цикл, но я его убрал функцией map и заработало гораздо быстрее! но я как не пытался ее не могу использовать в главной программе! Подскажите может ее все-таки как-то можно использовать или есть другие инструменты?
Офлайн
непонятно что у тебя за данные такие, обычно все в один проход делается
зайди в каталог БД, создай файл my.sqlite типа
.mode csv SELECT sql FROM sqlite_master; SELECT provider, geography FROM incomes;
sqlite3 providers.db <my.sqlite >db.txt
Офлайн
Данные типа Продавец и покупатель, с соответствующим номером, то есть один покупатель может взаимодействовать с многими продавцами, и один продавец с несколькими покупателями! А данные такие, что provider - это столбец в таблице продавца, а второй столбец geography - покупатель строк 50000 а столбцов всего 2.
Офлайн