22  Pandas - dane tekstowe

22.1 Normalizacja

Normalizacja danych tekstowych polega na przekształceniu tekstu w jednolity i porównywalny format. W Pandas można to osiągnąć poprzez zastosowanie różnych operacji na kolumnach zawierających dane tekstowe.

Stare podejście (na piechotę, pełna kontrola):

import pandas as pd

# Przykładowa ramka danych
data = pd.DataFrame({
    'Text': ['  Hello World  ', 'Pandas  Library43', '   Data   Science  ']
})

# Usunięcie białych znaków
data['Text'] = data['Text'].str.strip()
print(data)
# Konwersja do małych liter
data['Text'] = data['Text'].str.lower()
print(data)
# Konwersja do wielkich liter
data['Text'] = data['Text'].str.upper()
print(data)
# Usunięcie znaków specjalnych
data['Text'] = data['Text'].str.replace(r'[^\w\s]', '', regex=True)
print(data)
# Usunięcie liczb
data['Text'] = data['Text'].str.replace(r'\d+', '', regex=True)
print(data)
# Usunięcie duplikatów
data = data.drop_duplicates(subset='Text')
print(data)
                Text
0        Hello World
1  Pandas  Library43
2     Data   Science
                Text
0        hello world
1  pandas  library43
2     data   science
                Text
0        HELLO WORLD
1  PANDAS  LIBRARY43
2     DATA   SCIENCE
                Text
0        HELLO WORLD
1  PANDAS  LIBRARY43
2     DATA   SCIENCE
              Text
0      HELLO WORLD
1  PANDAS  LIBRARY
2   DATA   SCIENCE
              Text
0      HELLO WORLD
1  PANDAS  LIBRARY
2   DATA   SCIENCE

Nowsza wersja (wygodna, ale w detalach trudna)

import pandas as pd

# Utworzenie przykładowej serii z różnymi formami zapisu tego samego tekstu
s = pd.Series(['café', 'cafe\u0301', 'café'])

# Normalizacja do jednolitej formy
normalized = s.str.normalize('NFC')

# Sprawdzenie czy wszystkie wartości są teraz identyczne
print(normalized.nunique())  # Powinno zwrócić 1
1

Inne opcje: ‘NFC’, ‘NFKC’, ‘NFD’, ‘NFKD’

22.2 Operacje wektorowe na tekstach

Oto tabela w języku Markdown wyjaśniająca funkcje z pandas.Series.str i ich zastosowanie:

Funkcja Opis
len() Zwraca długość każdego ciągu znaków w serii.
lower() Konwertuje wszystkie znaki na małe litery.
translate() Zastępuje znaki według podanej mapy translacji.
islower() Sprawdza, czy wszystkie znaki w ciągu są małymi literami.
ljust() Justuje tekst w lewo, wypełniając go określonym znakiem do zadanej szerokości.
upper() Konwertuje wszystkie znaki na wielkie litery.
startswith() Sprawdza, czy ciąg znaków zaczyna się od podanego prefiksu.
isupper() Sprawdza, czy wszystkie znaki w ciągu są wielkimi literami.
rjust() Justuje tekst w prawo, wypełniając go określonym znakiem do zadanej szerokości.
find() Zwraca indeks pierwszego wystąpienia podciągu; zwraca -1, jeśli podciąg nie istnieje.
endswith() Sprawdza, czy ciąg znaków kończy się podanym sufiksem.
isnumeric() Sprawdza, czy ciąg zawiera tylko znaki numeryczne.
center() Centruje tekst, wypełniając go określonym znakiem do zadanej szerokości.
rfind() Zwraca indeks ostatniego wystąpienia podciągu; zwraca -1, jeśli podciąg nie istnieje.
isalnum() Sprawdza, czy ciąg zawiera tylko litery i cyfry.
isdecimal() Sprawdza, czy ciąg zawiera tylko znaki dziesiętne.
zfill() Wypełnia ciąg zerami z lewej strony, aby osiągnąć określoną długość.
index() Zwraca indeks pierwszego wystąpienia podciągu; zgłasza wyjątek, jeśli podciąg nie istnieje.
isalpha() Sprawdza, czy ciąg zawiera tylko litery.
split() Dzieli ciąg na listę podciągów na podstawie separatora (domyślnie spacja).
strip() Usuwa białe znaki (lub inne wskazane znaki) z obu stron ciągu.
rindex() Zwraca indeks ostatniego wystąpienia podciągu; zgłasza wyjątek, jeśli podciąg nie istnieje.
isdigit() Sprawdza, czy ciąg zawiera tylko cyfry.
rsplit() Dzieli ciąg od prawej strony na listę podciągów na podstawie separatora (domyślnie spacja).
rstrip() Usuwa białe znaki (lub inne wskazane znaki) z prawej strony ciągu.
capitalize() Zmienia pierwszą literę na wielką, a resztę na małe.
isspace() Sprawdza, czy ciąg zawiera tylko białe znaki.
partition() Dzieli ciąg na trzy części: przed separator, separator i po separatorze.
lstrip() Usuwa białe znaki (lub inne wskazane znaki) z lewej strony ciągu.
swapcase() Zmienia wielkość liter na przeciwną (małe na wielkie i odwrotnie).
istitle() Sprawdza, czy ciąg jest sformatowany jako tytuł (pierwsze litery wyrazów są wielkie).
rpartition() Dzieli ciąg na trzy części od prawej strony: przed separator, separator i po separatorze.

Zwykle operacje wektorowe są szybsze:

import time
import pandas as pd

# Tworzenie przykładowej ramki danych z 2000000 wierszami
data = {'Text': ['Pandas is awesome'] * 2000000}
data2 = pd.DataFrame(data)


# Funkcja, która konwertuje tekst na małe litery (przykładowa operacja)
def to_lower(text):
    return text.lower()


# 1. Operacja wektorowa
start_vectorized = time.time()
data2['Vectorized'] = data2['Text'].str.lower()
end_vectorized = time.time()

# 2. Operacja z list comprehension
start_comprehension = time.time()
data2['Comprehension'] = [to_lower(text) for text in data2['Text']]
end_comprehension = time.time()

# Czasy wykonania
vectorized_time = end_vectorized - start_vectorized
comprehension_time = end_comprehension - start_comprehension

# Wynik
print(vectorized_time, comprehension_time)
0.16231775283813477 0.31162595748901367