W poprzedniej części udało nam się policzyć 3-gramy i zapisać je do plików tekstowych. Przy odrobinie samozaparcia można tak zmienić formę i format plików, by dało się je zaimportować do Excela i tam prowadzić dalszą obróbkę. My zrobimy coś innego, użyjemy biblioteki Pandas, która wspiera typ danych nazywany Dataframe. W bardzo dużym uproszczeniu Dataframe to taki arkusz Excela: ma wiersze, kolumny i może mieć nazwy kolumn. Pandas to olbrzymia biblioteka Pythona, której możliwości rosną cały czas. Jeśli nie masz biblioteki Pandas, uruchom linię komend (klikając lupę koło znaczka Windows w lewym dolnym rogu, wpisując cmd i klikając enter) i wydaj polecenie pip install pandas, jeśli coś nie działa zapoznaj się z tą instrukcją.
Zaczniemy od zasilenia naszego Dataframe danymi, które uzyskaliśmy dzięki funkcji Counter().
from os import listdir
import re
from collections import Counter
import pandas as pd
sciezka = "F:\\python\\ids\\"
plik = "Bracia Dalcz i S-ka - Tadeusz Dolega-Mostowicz.txt"
ksiazka = open(sciezka + plik, mode="r", encoding = "utf-8")
tekst = ksiazka.read()
#przygotuj tekst do zliczania powtórzeń słów
tekst = tekst.replace("\n", " ")
tekst = tekst.lower()
tekst = re.sub("[^a-z ąćęłńóśóżź]", "", tekst)
tekst = re.sub(" +", " ", tekst)
wyrazy = tekst.split()
lista_trzech_wyrazow = []
#utwórz listę trzech kolejnych wyrazów
for indeks in range(len(wyrazy) - 2):
trzy_wyrazy = " ".join(wyrazy[indeks:indeks + 3])
lista_trzech_wyrazow.append(trzy_wyrazy)
#utwórz słownik zliczający liczbę powtórzeń trzech kolejnych wyrazów
liczba_trzygramow = Counter(lista_trzech_wyrazow)
#utwórz Dataframe (df) ze słownika
df = pd.DataFrame(liczba_trzygramow)
print(df)
W 4 linijce importujemy bilbiotekę Pandas. Standardem jest importowanie jej jako pd, dzięki temu w kodzie nie będziesz musiał pisać Pandas, by wykorzystać funkcje i metody tej biblioteki, wystarczy napisać pd. Nic nie stoi na przeszkodzie żeby np. zaimprować bibliotekę re jako reksio (import re as reksio) i zamiast re.sub() pisać reksio.sub(). W linijce 25 używamy funkcji DataFrame() (wielkość liter jest ważna) do zaimportowania słownika do Dataframe. Zobaczmy efekt:
======================== RESTART: F:/python38/wpis 14.py =======================
Traceback (most recent call last):
File "F:/python38/wpis 14.py", line 26, in <module>
df = pd.DataFrame(liczba_trzygramow)
File "F:\python38\lib\site-packages\pandas\core\frame.py", line 435, in __init__
mgr = init_dict(data, index, columns, dtype=dtype)
File "F:\python38\lib\site-packages\pandas\core\internals\construction.py", line 254, in init_dict
return arrays_to_mgr(arrays, data_names, index, columns, dtype=dtype)
File "F:\python38\lib\site-packages\pandas\core\internals\construction.py", line 64, in arrays_to_mgr
index = extract_index(arrays)
File "F:\python38\lib\site-packages\pandas\core\internals\construction.py", line 355, in extract_index
raise ValueError("If using all scalar values, you must pass an index")
ValueError: If using all scalar values, you must pass an index
>>>
Błąd, Pandas nie poradzi sobie z naszym słownikiem ot tak, nie wszystko co chcemy może stać się Dataframe, tak jak nie każdą tabelę da się bezpośrednio wkleić do Excela. Cofnijmy się o krok i poćwiczymy na prostym słowniku:
import pandas as pd
slownik = {"kogut ma dziób":4, "kura ma jajka":2, "pisklę ma dzióbek":3}
print(slownik)
#utwórz Dataframe (df) ze słownika
dane_pandas = pd.DataFrame(slownik)
print(dane_pandas)
W 1 linijce importujemy bibliotekę pandas. W 2 linijce przygotowujemy pod zmienną slownik nasz słownik. W 3 linijce drukujemy słownik. W 6 linijce próbujemy umieścić słownik w Dataframe, co jak wiemy nie uda się. 7 linijka będzie nam potrzebna do wizualizacji Datafarame. Dataframe nie przyjmie słownika, ale sprawdźmy czy przyjmie listę, zmieńmy program:
import pandas as pd
slownik = {"kogut ma dziób":4, "kura ma jajka":2, "pisklę ma dzióbek":3}
print(list(slownik))
#utwórz Dataframe (df) ze słownika
dane_pandas = pd.DataFrame(list(slownik))
print(dane_pandas)
W 3 i 6 linijce wymuszamy zmianę typu danych na listę funkcją list(). Zobaczmy efekt:
======================== RESTART: F:/python38/wpis 14.py =======================
['kogut ma dziób', 'kura ma jajka', 'pisklę ma dzióbek']
0
0 kogut ma dziób
1 kura ma jajka
2 pisklę ma dzióbek
>>>
Jest trochę lepiej. Lista znalazła się w Dataframe, ale jak widzimy, zmiana typu danych na listę pozbawiła nas wartości, zostały same klucze. Przyjrzyj się jeszcze Dataframe, prócz elementów listy, po lewej stronie są ponumerowane wiersze (od 0 do 2) a u góry numery kolumn (0), to trochę odpowiada numeracji w Excel, tyle, że w poziomie i pionie użyte są cyfry.
Spróbujmy inaczej. Użyjmy na słowniku metody .items(), która zwraca listę par składających się z klucza i wartości:
import pandas as pd
slownik = {"kogut ma dziób":4, "kura ma jajka":2, "pisklę ma dzióbek":3}
print(slownik.items())
#utwórz Dataframe (df) ze słownika
dane_pandas = pd.DataFrame(slownik.items())
print(dane_pandas)
Zobaczmy efekt:
======================== RESTART: F:/python38/wpis 14.py =======================
dict_items([('kogut ma dziób', 4), ('kura ma jajka', 2), ('pisklę ma dzióbek', 3)])
0 1
0 kogut ma dziób 4
1 kura ma jajka 2
2 pisklę ma dzióbek 3
>>>
O to nam chodziło, doszła druga kolumna z nr 1, w której znajdują się wartości. Dodajmy jeszcze nazwy kolumn poprzez parametr columns funkcji DataFrame():
import pandas as pd
slownik = {"kogut ma dziób":4, "kura ma jajka":2, "pisklę ma dzióbek":3}
print(slownik.items())
#utwórz Dataframe (df) ze słownika
dane_pandas = pd.DataFrame(slownik.items(), \
columns = ["trzygram", "liczba wystąpień"])
print(dane_pandas)
Parametr columns uzupełniamy listą , czyli podajemy wartości w kwadratowych nawiasach [], nazwy kolumn podajemy w kolejności ich numerowania, w naszym przypadku kolumna 0 otrzyma nazwę trzygram, kolumna 1 nazwę liczba wystąpień. Zobaczmy efekt:
======================== RESTART: F:/python38/wpis 14.py =======================
dict_items([('kogut ma dziób', 4), ('kura ma jajka', 2), ('pisklę ma dzióbek', 3)])
trzygram liczba wystąpień
0 kogut ma dziób 4
1 kura ma jajka 2
2 pisklę ma dzióbek 3
>>>
Wykorzystajmy te nowe umiejętności w naszym głównym programie dla jednej książki:
from os import listdir
import re
from collections import Counter
import pandas as pd
sciezka = "F:\\python\\ids\\"
plik = "Bracia Dalcz i S-ka - Tadeusz Dolega-Mostowicz.txt"
ksiazka = open(sciezka + plik, mode="r", encoding = "utf-8")
tekst = ksiazka.read()
#przygotuj tekst do zliczania powtórzeń słów
tekst = tekst.replace("\n", " ")
tekst = tekst.lower()
tekst = re.sub("[^a-z ąćęłńóśóżź]", "", tekst)
tekst = re.sub(" +", " ", tekst)
wyrazy = tekst.split()
lista_trzech_wyrazow = []
#utwórz listę trzech kolejnych wyrazów
for indeks in range(len(wyrazy) - 2):
trzy_wyrazy = " ".join(wyrazy[indeks:indeks + 3])
lista_trzech_wyrazow.append(trzy_wyrazy)
#utwórz słownik zliczający liczbę powtórzeń trzech kolejnych wyrazów
liczba_trzygramow = Counter(lista_trzech_wyrazow)
#utwórz Dataframe (df) ze słownika
df = pd.DataFrame(liczba_trzygramow.items(),columns = ["Trzygram","TDM Bracia"])
print(df)
I zobaczmy efekt:
========================== RESTART: F:\python38\wpis 14.py =========================
Trzygram TDM Bracia
0 tadeusz dołęgamostowicz bracia 2
1 dołęgamostowicz bracia dalcz 2
2 bracia dalcz i 7
3 dalcz i ska 5
4 i ska ta 1
... ... ...
136997 family cc by 1
136998 cc by isbn 1
136999 by isbn plik 1
137000 isbn plik wygenerowany 1
137001 plik wygenerowany dnia 1
[137002 rows x 2 columns]
>>>
Pandas jest na tyle przyjemną biblioteką, że nie zamorduje ci terminala drukowaniem wszystkich danych, jak widzisz z 137 002 wierszy wydrukował 5 pierwszych i 5 ostatnich. Dane dobrze jeszcze posortować, do tego służy funkcja sort_values(). Dodajmy ją do naszego programu:
from os import listdir
import re
from collections import Counter
import pandas as pd
sciezka = "F:\\python\\ids\\"
plik = "Bracia Dalcz i S-ka - Tadeusz Dolega-Mostowicz.txt"
ksiazka = open(sciezka + plik, mode="r", encoding = "utf-8")
tekst = ksiazka.read()
#przygotuj tekst do zliczania powtórzeń słów
tekst = tekst.replace("\n", " ")
tekst = tekst.lower()
tekst = re.sub("[^a-z ąćęłńóśóżź]", "", tekst)
tekst = re.sub(" +", " ", tekst)
wyrazy = tekst.split()
lista_trzech_wyrazow = []
#utwórz listę trzech kolejnych wyrazów
for indeks in range(len(wyrazy) - 2):
trzy_wyrazy = " ".join(wyrazy[indeks:indeks + 3])
lista_trzech_wyrazow.append(trzy_wyrazy)
#utwórz słownik zliczający liczbę powtórzeń trzech kolejnych wyrazów
liczba_trzygramow = Counter(lista_trzech_wyrazow)
#utwórz Dataframe (df) ze słownika
df = pd.DataFrame(liczba_trzygramow.items(),columns = ["Trzygram","TDM Bracia"])
print(df)
#posortuj od najliczniej występującego trzygramu
df = df.sort_values(by = "TDM Bracia", ascending = False)
print(df)
w 28 linijce podajemy argumenty funkcji sort_values(), pierwszy argument by = służy wskazaniu której kolumny do sortowania chcesz użyć, my nazwaliśmy kolumny dlatego podajemy jej nazwę. Podajemy też drugi argument, chcemy żeby w pierwszym wierszu Dataframe była największa wartość, a potem malała w kolejnych wierszach, czyli sortujemy malejąco. sort_values() ma domyślnie sortowanie rosnąco, dlatego musimy to zmienić podając argument ascending równy False. Zobaczmy efekt:
========================== RESTART: F:\python38\wpis 14.py =========================
Trzygram TDM Bracia
0 tadeusz dołęgamostowicz bracia 2
1 dołęgamostowicz bracia dalcz 2
2 bracia dalcz i 7
3 dalcz i ska 5
4 i ska ta 1
... ... ...
136997 family cc by 1
136998 cc by isbn 1
136999 by isbn plik 1
137000 isbn plik wygenerowany 1
137001 plik wygenerowany dnia 1
[137002 rows x 2 columns]
Trzygram TDM Bracia
1479 w każdym razie 55
5833 w ten sposób 40
5596 w ogóle nie 18
34019 w gruncie rzeczy 17
6899 ze względu na 17
... ... ...
47031 wskaże kilka spraw 1
47030 i wskaże kilka 1
47029 zadanie i wskaże 1
47028 mi zadanie i 1
137001 plik wygenerowany dnia 1
[137002 rows x 2 columns]
>>>
W naszym przypadku nie interesuje nas, co jest na końcu Dataframe, ale chętnie obejrzymy więcej niż 5 pierwszych wierszy. W Dataframe możemy użyć funkcji head(), której argumentem jest liczba wierszy do wyświetlenia. Zmieńmy 29 linijkę kodu:
from os import listdir
import re
from collections import Counter
import pandas as pd
sciezka = "F:\\python\\ids\\"
plik = "Bracia Dalcz i S-ka - Tadeusz Dolega-Mostowicz.txt"
ksiazka = open(sciezka + plik, mode="r", encoding = "utf-8")
tekst = ksiazka.read()
#przygotuj tekst do zliczania powtórzeń słów
tekst = tekst.replace("\n", " ")
tekst = tekst.lower()
tekst = re.sub("[^a-z ąćęłńóśóżź]", "", tekst)
tekst = re.sub(" +", " ", tekst)
wyrazy = tekst.split()
lista_trzech_wyrazow = []
#utwórz listę trzech kolejnych wyrazów
for indeks in range(len(wyrazy) - 2):
trzy_wyrazy = " ".join(wyrazy[indeks:indeks + 3])
lista_trzech_wyrazow.append(trzy_wyrazy)
#utwórz słownik zliczający liczbę powtórzeń trzech kolejnych wyrazów
liczba_trzygramow = Counter(lista_trzech_wyrazow)
#utwórz Dataframe (df) ze słownika
df = pd.DataFrame(liczba_trzygramow.items(),columns = ["Trzygram","TDM Bracia"])
print(df)
#posortuj od najliczniej występującego trzygramu
df = df.sort_values(by = "TDM Bracia", ascending = False)
print(df.head(10))
I zobaczmy efekt:
========================== RESTART: F:\python38\wpis 14.py =========================
Trzygram TDM Bracia
0 tadeusz dołęgamostowicz bracia 2
1 dołęgamostowicz bracia dalcz 2
2 bracia dalcz i 7
3 dalcz i ska 5
4 i ska ta 1
... ... ...
136997 family cc by 1
136998 cc by isbn 1
136999 by isbn plik 1
137000 isbn plik wygenerowany 1
137001 plik wygenerowany dnia 1
[137002 rows x 2 columns]
Trzygram TDM Bracia
1479 w każdym razie 55
5833 w ten sposób 40
5596 w ogóle nie 18
34019 w gruncie rzeczy 17
6899 ze względu na 17
26064 na myśl że 16
34971 o tym że 15
8993 w stosunku do 15
5834 ten sposób że 14
22992 się z nim 14
>>>
Fantastycznie! Zróbmy to samo dla wszystkich książek z katalogu:
from os import listdir
import re
from collections import Counter
import pandas as pd
sciezka = "F:\\python\\ids\\"
pliki = listdir(sciezka)
#dla każdego pliu w katalogu
for plik in pliki:
#otwórz plik
ksiazka = open(sciezka + plik, mode="r", encoding = "utf-8")
tekst = ksiazka.read()
#usuń kłopotliwe przypisek T. D. M. i przypisy
if plik == "Pamietnik pani Hanki - Tadeusz Dolega-Mostowicz.txt":
tekst = tekst.replace("(Przypisek T. D. M.)","")
elif plik == "Dziecko salonu - Janusz Korczak.txt" or \
plik == "Kiedy znow bede maly - Janusz Korczak.txt" or \
plik == "Bankructwo malego Dzeka - Janusz Korczak.txt":
tekst = tekst.split("Przypisy:")[0]
#przygotuj tekst do zliczania powtórzeń słów
tekst = tekst.replace("\n", " ")
tekst = tekst.lower()
tekst = re.sub("[^a-z ąćęłńóśóżź]", "", tekst)
tekst = re.sub(" +", " ", tekst)
wyrazy = tekst.split()
lista_trzech_wyrazow = []
#utwórz listę trzech kolejnych wyrazów
for indeks in range(len(wyrazy) - 2):
trzy_wyrazy = " ".join(wyrazy[indeks:indeks + 3])
lista_trzech_wyrazow.append(trzy_wyrazy)
#utwórz słownik zliczający liczbę powtórzeń trzech kolejnych wyrazów
liczba_trzygramow = Counter(lista_trzech_wyrazow)
#utwórz Dataframe (df) ze słownika
df = pd.DataFrame(liczba_trzygramow.items(),columns = ["Trzygram","TDM Bracia"])
#posortuj od najliczniej występującego trzygramu
df = df.sort_values(by = "TDM Bracia", ascending = False)
print(df.head(10))
I zobaczmy efekt:
======================== RESTART: F:\python38\wpis 14.py =======================
Trzygram TDM Bracia
3415 pani powiedziała że 11
6376 że się nie 8
6761 żeby się nie 8
33596 bo nie ma 7
19972 z mister taftem 7
2501 ale dżek nie 7
6803 to znaczy że 7
39081 bank dla dzieci 7
10163 do mister tafta 7
3947 na przyszły rok 7
Trzygram TDM Bracia
1479 w każdym razie 55
5833 w ten sposób 40
5596 w ogóle nie 18
34019 w gruncie rzeczy 17
6899 ze względu na 17
26064 na myśl że 16
34971 o tym że 15
8993 w stosunku do 15
5834 ten sposób że 14
22992 się z nim 14
Trzygram TDM Bracia
2719 w każdym razie 30
711 w związku z 12
20962 o tem że 10
8289 spojrzał na nią 10
8516 w ten sposób 9
11279 od czasu do 9
11280 czasu do czasu 9
11510 na myśl że 9
943 bądź co bądź 8
16334 z całej siły 8
Trzygram TDM Bracia
5274 w każdym razie 20
18308 okazało się że 12
301 w ten sposób 12
4133 o tem że 12
16694 w stosunku do 11
641 zwrócił się do 11
516 i po chwili 11
366 raz po raz 11
3330 się z nią 10
4727 spojrzał na nią 10
Trzygram TDM Bracia
1696 w tej chwili 13
14253 ja wiem że 8
7526 po raz pierwszy 8
10562 się z nim 7
2717 co to za 7
2480 nic więcej nie 7
17209 jak gdyby nie 7
9263 zdaje mi się 6
215 niech pan kupi 6
1417 w stronę wisły 6
Trzygram TDM Bracia
3107 co to jest 17
2879 ja nie chcę 13
38766 od izby do 9
38765 idę od izby 9
38767 izby do izby 9
33 mi się że 8
26807 ciastkami na guziku 8
26806 z ciastkami na 8
749 rozumie się że 7
1728 ha ha ha 6
Trzygram TDM Bracia
295 nie wie co 9
1607 co to za 9
1944 mu się nie 8
4327 że nie ma 7
6701 co się stało 7
5873 zdaje się że 6
7950 oparł się o 5
1508 nie bój się 5
9999 pyta się mama 5
12643 dziwi się kajtuś 5
Trzygram TDM Bracia
8614 kochany panie nikodemie 23
3510 che che che 18
304 raz po raz 15
5628 mu na myśl 15
596 że pan prezes 14
3019 w każdym razie 14
5629 na myśl że 14
8232 się z miejsca 13
3829 na wszelki wypadek 12
5627 przyszło mu na 12
Trzygram TDM Bracia
606 nie wiem czy 18
3759 nie wiem co 13
6044 się zdaje że 12
1009 sam nie wiem 11
696 a ja się 10
6188 kiedy byłem dorosły 10
4931 a on się 9
1036 żeby się nie 8
13406 i nic nie 8
3231 w tej chwili 8
Trzygram TDM Bracia
2206 do przekonania że 13
2783 w każdym razie 11
15278 okazało się że 10
22035 co się stało 10
8980 się z tym 9
1186 przyszło mu na 9
6586 mi się że 9
1187 mu na myśl 9
4527 od czasu do 8
4528 czasu do czasu 8
Trzygram TDM Bracia
483 wasza królewska mość 27
44457 dziś popr forma 22
1196 waszej królewskiej mości 18
70 na bezludną wyspę 18
2723 na bezludnej wyspie 16
5868 nie wie maciuś 10
13473 pyta się maciuś 10
9133 co to za 10
44730 forma os lp 8
4163 i nic nie 8
Trzygram TDM Bracia
2257 w każdym razie 40
2899 o tym że 28
5358 okazało się że 22
4711 wydaje mi się 22
2672 spojrzał na mnie 22
6488 w ten sposób 20
7494 na myśl że 20
1327 się ze mną 19
2742 się nad tym 18
1451 mi się że 17
>>>
Jest nieźle, chociaż tytuł drugiej kolumny powinien oddawać tytuł książki. Można to zmienić na wiele sposobów, np. zamiast podanej nazwy kolumny możemy użyć nazwy pliku (przy okazji skrócimy wyświetlanie do 5 wierszy Dataframe):
from os import listdir
import re
from collections import Counter
import pandas as pd
sciezka = "F:\\python\\ids\\"
pliki = listdir(sciezka)
#dla każdego pliu w katalogu
for plik in pliki:
#otwórz plik
ksiazka = open(sciezka + plik, mode="r", encoding = "utf-8")
tekst = ksiazka.read()
#usuń kłopotliwe przypisek T. D. M. i przypisy
if plik == "Pamietnik pani Hanki - Tadeusz Dolega-Mostowicz.txt":
tekst = tekst.replace("(Przypisek T. D. M.)","")
elif plik == "Dziecko salonu - Janusz Korczak.txt" or \
plik == "Kiedy znow bede maly - Janusz Korczak.txt" or \
plik == "Bankructwo malego Dzeka - Janusz Korczak.txt":
tekst = tekst.split("Przypisy:")[0]
#przygotuj tekst do zliczania powtórzeń słów
tekst = tekst.replace("\n", " ")
tekst = tekst.lower()
tekst = re.sub("[^a-z ąćęłńóśóżź]", "", tekst)
tekst = re.sub(" +", " ", tekst)
wyrazy = tekst.split()
lista_trzech_wyrazow = []
#utwórz listę trzech kolejnych wyrazów
for indeks in range(len(wyrazy) - 2):
trzy_wyrazy = " ".join(wyrazy[indeks:indeks + 3])
lista_trzech_wyrazow.append(trzy_wyrazy)
#utwórz słownik zliczający liczbę powtórzeń trzech kolejnych wyrazów
liczba_trzygramow = Counter(lista_trzech_wyrazow)
#utwórz Dataframe (df) ze słownika
df = pd.DataFrame(liczba_trzygramow.items(),columns = ["Trzygram",plik])
#posortuj od najliczniej występującego trzygramu
df = df.sort_values(by = plik, ascending = False)
print(df.head(5))
W 35 i 37 linijce zamiast ustalonej na sztywno nazwy odwołujemy się do wartości zmiennej plik. Efekt:
======================== RESTART: F:\python38\wpis 14.py =======================
Trzygram Bankructwo malego Dzeka - Janusz Korczak.txt
3415 pani powiedziała że 11
6376 że się nie 8
6761 żeby się nie 8
33596 bo nie ma 7
19972 z mister taftem 7
Trzygram Bracia Dalcz i S-ka - Tadeusz Dolega-Mostowicz.txt
1479 w każdym razie 55
5833 w ten sposób 40
5596 w ogóle nie 18
34019 w gruncie rzeczy 17
6899 ze względu na 17
Trzygram Dr. Murek zredukowany - Tadeusz Dolega-Mostowicz.txt
2719 w każdym razie 30
711 w związku z 12
20962 o tem że 10
8289 spojrzał na nią 10
8516 w ten sposób 9
Trzygram Drugie zycie doktora Murka - Tadeusz Dolega-Mostowicz.txt
5274 w każdym razie 20
18308 okazało się że 12
301 w ten sposób 12
4133 o tem że 12
16694 w stosunku do 11
Trzygram Dzieci ulicy - Janusz Korczak.txt
1696 w tej chwili 13
14253 ja wiem że 8
7526 po raz pierwszy 8
10562 się z nim 7
2717 co to za 7
Trzygram Dziecko salonu - Janusz Korczak.txt
3107 co to jest 17
2879 ja nie chcę 13
38766 od izby do 9
38765 idę od izby 9
38767 izby do izby 9
Trzygram Kajtus Czarodziej - Janusz Korczak.txt
295 nie wie co 9
1607 co to za 9
1944 mu się nie 8
4327 że nie ma 7
6701 co się stało 7
Trzygram Kariera Nikodema Dyzmy - Tadeusz Dolega-Mostowicz.txt
8614 kochany panie nikodemie 23
3510 che che che 18
304 raz po raz 15
5628 mu na myśl 15
596 że pan prezes 14
Trzygram Kiedy znow bede maly - Janusz Korczak.txt
606 nie wiem czy 18
3759 nie wiem co 13
6044 się zdaje że 12
1009 sam nie wiem 11
696 a ja się 10
Trzygram Kiwony - Tadeusz Dolega-Mostowicz.txt
2206 do przekonania że 13
2783 w każdym razie 11
15278 okazało się że 10
22035 co się stało 10
8980 się z tym 9
Trzygram Krol Macius na wyspie bezludnej - Janusz Korczak.txt
483 wasza królewska mość 27
44457 dziś popr forma 22
1196 waszej królewskiej mości 18
70 na bezludną wyspę 18
2723 na bezludnej wyspie 16
Trzygram Pamietnik pani Hanki - Tadeusz Dolega-Mostowicz.txt
2257 w każdym razie 40
2899 o tym że 28
5358 okazało się że 22
4711 wydaje mi się 22
2672 spojrzał na mnie 22
>>>
Teraz wiadomo, co przedstawia każdy z Dataframe, ale nazwy kolumny są trochę za długie. Może uda nam się je poprawić. Dobrze by mieć na początku inicjały autora, a potem tytuł. Mamy już cały wachlarz umiejętności pozwalający na taką zmianę. Ja bym zrobił to tak. Popatrz, możesz wyświetlić listę z nazwami plików:
from os import listdir
sciezka = "F:\\python\\ids\\"
pliki = listdir(sciezka)
print(pliki)
Lista wygląda tak:
======================== RESTART: F:\python38\wpis 14.py =======================
['Bankructwo malego Dzeka - Janusz Korczak.txt', 'Bracia Dalcz i S-ka - Tadeusz Dolega-Mostowicz.txt', 'Dr. Murek zredukowany - Tadeusz Dolega-Mostowicz.txt', 'Drugie zycie doktora Murka - Tadeusz Dolega-Mostowicz.txt', 'Dzieci ulicy - Janusz Korczak.txt', 'Dziecko salonu - Janusz Korczak.txt', 'Kajtus Czarodziej - Janusz Korczak.txt', 'Kariera Nikodema Dyzmy - Tadeusz Dolega-Mostowicz.txt', 'Kiedy znow bede maly - Janusz Korczak.txt', 'Kiwony - Tadeusz Dolega-Mostowicz.txt', 'Krol Macius na wyspie bezludnej - Janusz Korczak.txt', 'Pamietnik pani Hanki - Tadeusz Dolega-Mostowicz.txt']
Cały pomysł opiera się na już posiadanych danych jakie mamy w elementach listy. Pomyśl chwilę, wybierz własną metodę i sprawdź, czy uda ci się utworzyć listę inicjałów i tytułów. Potem zerknij na mój sposób:
from os import listdir
sciezka = "F:\\python\\ids\\"
pliki = listdir(sciezka)
tytuly = []
print(pliki)
for plik in pliki:
if plik.find("Tadeusz Dolega-Mostowicz") > -1:
autor = "TDM"
tytul = plik.split(" - Tadeusz Dolega-Mostowicz")[0]
else:
autor = "JK"
tytul = plik.split(" - Janusz Korczak")[0]
tytuly.append(f"{autor} {tytul}")
print(tytuly)
Co zrobiłem? W 5 linijce stworzyłem pustą listę, w której znajdą się skrócone tytuły. W 8 linijce dla każdego elementu listy używam metody .find(), w jej argumencie podajesz tekst do znalezienia. Metoda zwraca liczbę wskazującą pierwszy indeks podanego do wyszukania ciągu znaków, jeśli szukanego tekstu nie ma w stringu metoda zwraca wartość -1. Czyli 8 linijkę można przeczytać tak Jeśli w elemencie listy występuje „Tadeusz Dolega-Mostowicz” (wartość .find() większa od -1) to: . W 9 linijce pod zmienną autor podstawiam inicjały, a pod zmienną tytul fragment stringa znajdujący się przed ” – Tadeusz Dolega-Mostowicz” oznaczającym autora. W 11 linijce zaczyna się warunek, gdy metoda .find() zwróci wartość mniejszą niż 0. W tym wypadku autorem staje się JK, a tytuł jest fragmentem stringa, w którym występuje ciąg ” – Janusz Korczak”. W 14 linijce łączymy zmienną autor i tytuł, by uzyskać zakładany efekt. Zobaczmy go:
======================== RESTART: F:\python38\wpis 14.py =======================
['JK Bankructwo malego Dzeka', 'TDM Bracia Dalcz i S-ka', 'TDM Dr. Murek zredukowany', 'TDM Drugie zycie doktora Murka', 'JK Dzieci ulicy', 'JK Dziecko salonu', 'JK Kajtus Czarodziej', 'TDM Kariera Nikodema Dyzmy', 'JK Kiedy znow bede maly', 'TDM Kiwony', 'JK Krol Macius na wyspie bezludnej', 'TDM Pamietnik pani Hanki']
>>>
Można jeszcze naszą pętlę uładnić:
from os import listdir
sciezka = "F:\\python\\ids\\"
pliki = listdir(sciezka)
autortytul = []
for plik in pliki:
if plik.find("Tadeusz Dolega-Mostowicz") > -1:
autortytul.append(f"TDM {plik.split(' - Tadeusz Dolega-Mostowicz')[0]}")
else:
autortytul.append(f"JK {plik.split(' - Janusz Korczak')[0]}")
print(autortytul)
W powyższym kodzie pozbywamy się zmiennych autor i tytul. Zamiast nich używamy fstring, co oszczędza nam 4 linijki i dwie zmienne. Zauważ konieczność zastosowania w metodzie .split() pojedynczych cudzysłowów. Efekt działania:
======================== RESTART: F:\python38\wpis 14.py =======================
['JK Bankructwo malego Dzeka', 'TDM Bracia Dalcz i S-ka', 'TDM Dr. Murek zredukowany', 'TDM Drugie zycie doktora Murka', 'JK Dzieci ulicy', 'JK Dziecko salonu', 'JK Kajtus Czarodziej', 'TDM Kariera Nikodema Dyzmy', 'JK Kiedy znow bede maly', 'TDM Kiwony', 'JK Krol Macius na wyspie bezludnej', 'TDM Pamietnik pani Hanki']
>>>
Wszystko działa, możemy użyć tego kodu w głównym programie:
from os import listdir
import re
from collections import Counter
import pandas as pd
sciezka = "F:\\python\\ids\\"
pliki = listdir(sciezka)
#dla każdego pliu w katalogu
for plik in pliki:
#otwórz plik
ksiazka = open(sciezka + plik, mode="r", encoding = "utf-8")
tekst = ksiazka.read()
#usuń kłopotliwe przypisek T. D. M. i przypisy
if plik == "Pamietnik pani Hanki - Tadeusz Dolega-Mostowicz.txt":
tekst = tekst.replace("(Przypisek T. D. M.)","")
elif plik == "Dziecko salonu - Janusz Korczak.txt" or \
plik == "Kiedy znow bede maly - Janusz Korczak.txt" or \
plik == "Bankructwo malego Dzeka - Janusz Korczak.txt":
tekst = tekst.split("Przypisy:")[0]
#przygotuj tekst do zliczania powtórzeń słów
tekst = tekst.replace("\n", " ")
tekst = tekst.lower()
tekst = re.sub("[^a-z ąćęłńóśóżź]", "", tekst)
tekst = re.sub(" +", " ", tekst)
wyrazy = tekst.split()
lista_trzech_wyrazow = []
#utwórz listę trzech kolejnych wyrazów
for indeks in range(len(wyrazy) - 2):
trzy_wyrazy = " ".join(wyrazy[indeks:indeks + 3])
lista_trzech_wyrazow.append(trzy_wyrazy)
#utwórz słownik zliczający liczbę powtórzeń trzech kolejnych wyrazów
liczba_trzygramow = Counter(lista_trzech_wyrazow)
#nadaj tytuł kolumnie zliaczania równy inicjałom i tytułowi książki
if plik.find("Tadeusz Dolega-Mostowicz") > -1:
autortytul = (f"TDM {plik.split(' - Tadeusz Dolega-Mostowicz')[0]}")
else:
autortytul = (f"JK {plik.split(' - Janusz Korczak')[0]}")
#utwórz Dataframe (df) ze słownika
df = pd.DataFrame(liczba_trzygramow.items(),columns = ["Trzygram",autortytul])
#posortuj od najliczniej występującego trzygramu
df = df.sort_values(by = autortytul, ascending = False)
print(df.head(5))
Nadawanie tytułów zaczyna się w 34 linijce, oczywiście nie musimy tworzyć żadnego słownika w naszym przypadku, odpowiedni tytuł generowany jest na bieżąco ze zmiennej plik. Zobaczmy efekt:
======================== RESTART: F:\python38\wpis 14.py =======================
Trzygram JK Bankructwo malego Dzeka
3415 pani powiedziała że 11
6376 że się nie 8
6761 żeby się nie 8
33596 bo nie ma 7
19972 z mister taftem 7
Trzygram TDM Bracia Dalcz i S-ka
1479 w każdym razie 55
5833 w ten sposób 40
5596 w ogóle nie 18
34019 w gruncie rzeczy 17
6899 ze względu na 17
Trzygram TDM Dr. Murek zredukowany
2719 w każdym razie 30
711 w związku z 12
20962 o tem że 10
8289 spojrzał na nią 10
8516 w ten sposób 9
Trzygram TDM Drugie zycie doktora Murka
5274 w każdym razie 20
18308 okazało się że 12
301 w ten sposób 12
4133 o tem że 12
16694 w stosunku do 11
Trzygram JK Dzieci ulicy
1696 w tej chwili 13
14253 ja wiem że 8
7526 po raz pierwszy 8
10562 się z nim 7
2717 co to za 7
Trzygram JK Dziecko salonu
3107 co to jest 17
2879 ja nie chcę 13
38766 od izby do 9
38765 idę od izby 9
38767 izby do izby 9
Trzygram JK Kajtus Czarodziej
295 nie wie co 9
1607 co to za 9
1944 mu się nie 8
4327 że nie ma 7
6701 co się stało 7
Trzygram TDM Kariera Nikodema Dyzmy
8614 kochany panie nikodemie 23
3510 che che che 18
304 raz po raz 15
5628 mu na myśl 15
596 że pan prezes 14
Trzygram JK Kiedy znow bede maly
606 nie wiem czy 18
3759 nie wiem co 13
6044 się zdaje że 12
1009 sam nie wiem 11
696 a ja się 10
Trzygram TDM Kiwony
2206 do przekonania że 13
2783 w każdym razie 11
15278 okazało się że 10
22035 co się stało 10
8980 się z tym 9
Trzygram JK Krol Macius na wyspie bezludnej
483 wasza królewska mość 27
44457 dziś popr forma 22
1196 waszej królewskiej mości 18
70 na bezludną wyspę 18
2723 na bezludnej wyspie 16
Trzygram TDM Pamietnik pani Hanki
2257 w każdym razie 40
2899 o tym że 28
5358 okazało się że 22
4711 wydaje mi się 22
2672 spojrzał na mnie 22
>>>
Świetnie! W następnej części spróbujemy zaoszczędzić czas i procesor.
Zadanie domowe
Podążanie za instrukcjami, nawet jeśli je wszystkie wykonujesz samodzielnie, nie zrobi z ciebie programisty. Zadania domowe mogą wydawać się na początku trudne. Tu nie ma rozwiązania podanego na talerzu, użyj dowolnych źródeł, by znaleźć odpowiedź. To był bardzo długi rozdział, zadania są delikatne.
- Wyświetl typy danych naszego Dataframe, zmień typ danych liczby 3-gramów na string, jaki typ danych się wyświetli teraz?
- Znajdź sposób na zmianę nazw kolumn.