Code-Optimierung: Auftauchen eines Wortes überprüfen

Code-Stücke können hier veröffentlicht werden.
Antworten
pytony
User
Beiträge: 25
Registriert: Mittwoch 14. Juni 2017, 11:26

Liebe python-Benutzer!

Ich habe einen Code geschrieben, der eine Liste mit Wörtern mit mehreren Texten abgleicht. Hierfür habe ich die Liste in eine Dictionary umgewandelt,
damit jedes Key mehrere Values erhält und das in Form einer Liste (damit es später in ein Dataframe in pandas umgewandelt wird).
Taucht ein Wort in einem Text auf, erhält das Key per ".append" den Wert 1. Wenn nicht, dann 0. u.s.w..

"relevante wörter.xlsx" (108 KB) enthält eine Spalte mit den Wörtern, wonach gesucht werden soll.
"heise_archiv.csv" (766 MB) enthält die Texte etc..


Der Code geht alle Texte der heise news durch, aber ab den Punkt, wo die beiden DataFrames verkettet werden müssen, frisst Python mein Arbeitsspeicher (16GB DDR3)
und fängt an auf meine zweite SSD (1 TB) auszulagern. Woran liegt das? Und wie könnte man das ganze optimieren?

Hierfür habe ich den folgenden Code geschrieben:

Code: Alles auswählen

#####################IMPORT LIST#########################################################################
import pandas as pd
import openpyxl
import logging

logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO,
                    filename='word_counter.log')
import pickle
import time

start = time.time()


word_list = pd.read_excel("relevante wörter.xlsx", sheet_name="ALL Summary_extended", header=0, usecols=[0])[["Gesamt"]]
keywords = []
for index, row in word_list.iterrows():
    keywords.append(row["Gesamt"])

dic_keywords = {key.lower(): [] for key in keywords}

print(dic_keywords)


heise_archiv_csv = pd.read_csv(filepath_or_buffer='heise_archiv.csv', sep=',', header=0,
                               usecols=['titel', 'link', 'month', 'year', 'date', 'url', 'text', 'text2', 'month_year',
                                        'quarter', 'title'])[['month_year', 'link', 'url', 'title', 'text2']]

heise_collection = []
documents_heise = []
list_heise = []

for index, row in heise_archiv_csv.iterrows():
    i = 0
    date = row['month_year']
    print(date)
    url = row['url']
    title = row['title']
    text = str(row['text2']).lower()

    for key, value in dic_keywords.items():
        if text.find(key):
            dic_keywords[key].append(1)
            i += 1
        else:
            dic_keywords[key].append(0)
            
    keyword_hits = i

    list_heise.append({'date': date,
                       'url': str(url),
                       'title': str(text),
                       'keyword_hits': int(keyword_hits)})

with open('heise_hit_list_dictionary.pickle', 'wb') as handle:
    pickle.dump(dic_keywords, handle, protocol=pickle.HIGHEST_PROTOCOL)

complete_heise_archive = pd.DataFrame(data=list_heise, columns=["date", "url", "title", "keyword_hits"])
keyword_hits_dataframe = pd.DataFrame.from_dict(data=dic_keywords)
final_dataframe = pd.concat([complete_heise_archive, keyword_hits_dataframe], axis=1)
writer = pd.ExcelWriter("hits_result.xlsx", engine='openpyxl')
final_dataframe.to_excel(writer, sheet_name='hits_table')
writer.save()

end = time.time()
elapsed_time = end - start
print(str(time.strftime("%H:%M:%S", time.gmtime(elapsed_time))))

Ich bedanke mich sehr im Voraus! :-)

LG
pytony
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Du legst für jedes Keyword eine Liste mit so vielen Einträgen wie Artikel an. Bei ein paar Tausend Wörtern und ein paar Tausend Artikeln gibt das ein paar Millionen Listeneinträge.
Geht viel effizienter mit Pandas-Mitteln und als Ergebnis eine einfache Bool-Matrix, aber bei ein paar GB Arbeitsspeicher sollte die Verschwendung noch nicht ernsthafte Folgen haben, außer ich hab mich bei meiner Überschlagsrechnung irgendwo verschätzt.
Also: mit Pandas arbeiten. dic_keywords und list_heise sind überflüssig. heise_collection und documents_heise werden gar nicht benutzt. Pickle ist nicht gerade effizient, bei Deiner nicht effizienten Datenstruktur. Die for-Schleifen sind allesamt überflüssig, wenn Du Pandas benutzt. Strings nochmal mehrfach in Strings umzuwandeln, macht sie nicht noch Stringiger.
pytony
User
Beiträge: 25
Registriert: Mittwoch 14. Juni 2017, 11:26

@Sirius3: Vielen lieben Dank für die Kritik!
Sirius3 hat geschrieben: Samstag 16. Februar 2019, 22:27 Geht viel effizienter mit Pandas-Mitteln und als Ergebnis eine einfache Bool-Matrix, aber bei ein paar GB Arbeitsspeicher sollte die Verschwendung noch nicht ernsthafte Folgen haben, außer ich hab mich bei meiner Überschlagsrechnung irgendwo verschätzt.
Sirius3 hat geschrieben: Samstag 16. Februar 2019, 22:27 Die for-Schleifen sind allesamt überflüssig, wenn Du Pandas benutzt. Strings nochmal mehrfach in Strings umzuwandeln, macht sie nicht noch Stringiger.
Sirius3 hat geschrieben: Samstag 16. Februar 2019, 22:27 Pickle ist nicht gerade effizient, bei Deiner nicht effizienten Datenstruktur.
Klingt alles ganz gut. Kannst du mir bitte zumindest ein paar Stichwörter bzw. Befehle bzgl. Pandas geben, sodass ich es nachschlagen kann und mehr daraus lernen kann? :-)


lg
pytony
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Wie ich gerade sehe, wird es wohl beim Schreiben einer riesigen Excel-Tabelle krachen.

Die Stichworte sind, ein Pandas-Tutorial durchzuarbeiten.

Was dann so aussehen könnte:

Code: Alles auswählen

import pandas as pd

words = pd.read_excel("relevante wörter.xlsx", sheet_name="ALL Summary_extended", header=0, usecols=[0])
keywords = words["Gesamt"].str.lower()

heise_archiv = pd.read_csv('heise_archiv.csv', sep=',', header=0,
                               usecols=['titel', 'link', 'month', 'year', 'date', 'url', 'text', 'text2', 'month_year',
                                        'quarter', 'title'])

text = heise_archiv['text2'].str.lower()
keyword_hits = keywords.apply(text.str.contains)
complete_heise_archive = heise_archiv[['month_year', 'url', 'title']]
complete_heise_archive['keyword_hits'] = keyword_hits.sum()
complete_heise_archive[keywords] = keyword_hits.T
complete_heise_archive.to_csv('hits_result.csv')
pytony
User
Beiträge: 25
Registriert: Mittwoch 14. Juni 2017, 11:26

Alles klar, Sirius3 :-) Das werde ich machen @Pandas Tutorial. Mal sehen, was Google dazu sagt. Falls du gute Quellen kennst, dann nehme ich die auch gerne an.

Tausend Dank für das Beispiel! Ich werde es heute Nachmittag/Abend direkt mal ausprobieren.

Die Excel Tabelle ist tatsächlich entstanden.....nach 55 min xD Das sollte ich lieber mal schnell verbessern ^^

Beste Grüße
pytony
Antworten