Un rappel que lors du traitement de texte avec des pandas, vous n'obtenez pas "Je ne sais pas, alors utilisez une phrase pour".
Collectez des informations dans le but de prétraiter le texte japonais.
J'apprécierais que vous me disiez s'il existe une meilleure méthode de traitement.
Environnement d'exécution
pandas 0.25.3
TL;DR
df [" nom de colonne "]. Str
--Si vous voulez faire quelque chose qui n'est pas implémenté dans pandas df [" nom de colonne "] .apply ()
Stockez des informations sur les marques de mode pour femmes extraites de HP. Le nom de l'entreprise, le nom de la marque, le nom du magasin et l'adresse sont stockés dans csv.
Puisqu'il est gratté à partir de plusieurs HP, il n'est pas unifié tel que demi-largeur pleine largeur et vierge. Le code postal peut être inclus ou non.
Le tableau ci-dessous est un exemple de données. Le résultat de l'exécution est également décrit en utilisant ces données à titre d'exemple.
company | brand | location | address |
---|---|---|---|
pal | BONbazaar | Bombazare Tokyo Dome City La Coeur | 1-1 Kasuga, Bunkyo-ku, Tokyo-1 Bâtiment La Coeur 2F |
world | index | Style Emio | 1 Takada Baba, Shinjuku-ku, Tokyo-35-3 Style Emio 1F |
pal | Whim Gazette | Magasin Marunouchi | 〒100-6390 2 Marunouchi, Chiyoda-ku, Tokyo-4-1 Bâtiment Marunouchi B1F |
stripe | SEVENDAYS=SUNDAY | Centre commercial Aeon Urawa Misono 2F | 5-50-1, Misono, Midori-ku, Saitama-shi, Saitama Aeon Mall Urawa Misono |
pal | mystic | Magasin Funabashi | 〒273-0012 2 Hamacho, Funabashi City, Préfecture de Chiba-1-1 LaLaport TOKYO-BAY LaLaport 3 |
pal | pual ce cin | Magasin Ofuna Lumine Wing | 〒247-0056 1 Ofuna, ville de Kamakura, préfecture de Kanagawa-4-1 Aile Lumine 4F |
stripe | Green Parks | Boutique sara Chapo Koiwa | 7 Minamikoiwa, Edogawa-ku, Tokyo-24-15 Chapo Koiwa 1F |
pal | Discoat | Discoat Petit Ikebukuro Shopping Park | 〒171-8532 1 Minami Ikebukuro, Toyoshima-ku, Tokyo-29-1 Ikebukuro SP B1F |
adastoria | niko and... | Atre Kawagoe | 105 Wakita-cho, Kawagoe-shi, Saitama Atre Kawagoe 4F |
pal | CIAOPANIC TYPY | Magasin Kameari | 〒125-0061 3 Kameari, Katsushika-ku, Tokyo-49-3 Ario Kameari 2F |
Comme une seule colonne (colonne ʻaddress`) est utilisée pour l'explication, le traitement de Series est presque introduit, mais le traitement de DataFrame est également décrit autant que possible.
Fondamentalement, dans Series.str
, méthode de chaîne python et [opération d'expression régulière] Vous pouvez appeler (https://docs.python.org/ja/3/library/re.html), vous pouvez donc les utiliser.
――Extraits d'articles fréquemment utilisés --Si vous souhaitez vérifier toutes les méthodes, veuillez vous référer au document officiel. --Référence: Résultats de la recherche Series.str - Working with text data — pandas 1.0.1 documentation
strip
Supprimez les caractères vides au début et à la fin de la chaîne de caractères.
df['strip']=df['address'].str.strip()
Bien entendu, «Series.str.rstrip», qui ne supprime que le début, et «lstrip», qui ne supprime que la fin, sont également implémentés.
split, rsplit
--Split la chaîne par le séparateur spécifié et retourne-la dans * list * --Si vous définissez ʻexpand = True`, vous pouvez diviser en plusieurs colonnes.
df['address'].str.split(expand=True)
0 | 1 | 2 |
---|---|---|
1-1 Kasuga, Bunkyo-ku, Tokyo-1 | Édifice La Coeur | 2F |
1 Takada Baba, Shinjuku-ku, Tokyo-35-3 | Style Emio | 1F |
〒100-6390 | 2 Marunouchi, Chiyoda-ku, Tokyo-4-1 | Bâtiment Marunouchi B1F |
5-50-1, Misono, Midori-ku, Saitama-shi, Saitama | Centre commercial Aeon Urawa Misono | None |
〒273-0012 2 Hamacho, Funabashi City, Préfecture de Chiba-1-1 | LaLaport TOKYO-BAY LaLaport 3 | None |
〒247-0056 | 1 Ofuna, ville de Kamakura, préfecture de Kanagawa-4-1 | Lumine Wing 4F |
7 Minamikoiwa, Edogawa-ku, Tokyo-24-15 Chapo Koiwa | 1F | None |
〒171-8532 1 Minami Ikebukuro, Toyoshima-ku, Tokyo-29-1 Ikebukuro SP | B1F | None |
Ville de Wakita, ville de Kawagoe, préfecture de Saitama | 105 | Atre Kawagoe 4F |
〒125-0061 3 Kameari, Katsushika-ku, Tokyo-49-3 Ario Kameari 2F | None | None |
rsplit
-Split du côté droitn
--Par exemple, si vous définissez n = 1
, le nombre de colonnes sera fixé à 2 car il ne sera divisé qu'une seule fois.df['address'].str.rsplit(expand=True, n=1)
0 | 1 |
---|---|
1-1 Kasuga, Bunkyo-ku, Tokyo-1 Édifice La Coeur | 2F |
1 Takada Baba, Shinjuku-ku, Tokyo-35-3 style Emio | 1F |
〒100-6390 2 Marunouchi, Chiyoda-ku, Tokyo-4-1 | Bâtiment Marunouchi B1F |
5-50-1, Misono, Midori-ku, Saitama-shi, Saitama | Centre commercial Aeon Urawa Misono |
〒273-0012 2 Hamacho, Funabashi City, Préfecture de Chiba-1-1 | LaLaport TOKYO-BAY LaLaport 3 |
〒247-0056 1 Ofuna, ville de Kamakura, préfecture de Kanagawa-4-1 | Lumine Wing 4F |
7 Minamikoiwa, Edogawa-ku, Tokyo-24-15 Chapo Koiwa | 1F |
〒171-8532 1 Minami Ikebukuro, Toyoshima-ku, Tokyo-29-1 Ikebukuro SP | B1F |
105 Wakita-cho, Kawagoe-shi, Saitama | Atre Kawagoe 4F |
〒125-0061 3 Kameari, Katsushika-ku, Tokyo-49-3 Ario Kameari 2F | None |
find
str.find
--Retourne la position de la chaîne si incluse, ** - 1 ** si non inclusedf['address'].str.find('Tokyo')
>> 0 0
1 0
2 10
3 -1
4 -1
5 -1
6 0
7 9
8 -1
9 9
df [df ['adresse']. str.find ('Tokyo')]
--df.query ('address.str.find ("Tokyo")')
hoge in hogehoge
, vous devez utiliser contains
.#Pour le moment"Tokyo"Il est également possible de spécifier une colonne qui ne contient pas
df.query('address.str.find("Tokyo")!=-1')
normalize Series.str.normalize
Principalement, les nombres et les symboles pleine largeur sont convertis en demi-largeur et le katakana demi-largeur est converti en pleine largeur. Spécifiez «NFKC» (forme normale KC) pour la forme.
# string
import unicodedata
unicodedata.normalize('NFKC', '123! ?? @ # Hankaku Katakana')
>> '123!?@#Hankaku Katakana'
# pandas
df['normalize'] = df['address'].str.normalize(form='NFKC')
Référence: Liste des caractères normalisés par unicodedata.normalize ('NFKC', x) en Python
findall
--Equivalent à re.findall ()
str.find ()
, vous pouvez utiliser des expressions régulières ici
--Retourne tous les mots correspondantsdf['address'].str.findall('(.{2}quartier)')
>> 0 [Quartier Bunkyo]
1 [Quartier Shinjuku]
2 [Quartier de Shirota]
3 [Quartier de la ville de Midori]
4 []
5 []
6 [Quartier Togawa]
7 [Quartier de Toshima]
8 []
9 [Katsushika]
contains
--contain ** s **, alors soyez prudent
--Fonctionnellement re.match ()
--Parce que la valeur booléenne est renvoyée, elle peut être utilisée pour affiner les données.
df['address'].str.contains('.{2}quartier')
>> 0 True
1 True
2 True
3 True
4 False
5 False
6 True
7 True
8 False
9 True
# "○○ salle"Afficher uniquement les données contenant
df.query('address.str.contains(".{2}quartier")')['address']
>>0 1-1 Kasuga, Bunkyo-ku, Tokyo-1 Bâtiment La Coeur 2F
1 Takada Baba, Shinjuku-ku, Tokyo 1-35-3 Style Emio 1F
2 〒100-6390 2 Marunouchi, Chiyoda-ku, Tokyo-4-1 Bâtiment Marunouchi B1F
3 5-50-1 Misono, Midori-ku, Saitama-shi, Saitama Aeon Mall Urawa Misono
6 Minamikoiwa, Edogawa-ku, Tokyo 7-24-15 Chapo Koiwa 1F
7 〒171-8532 1 Minami Ikebukuro, Toyoshima-ku, Tokyo-29-1 Ikebukuro SP B1F
9 〒125-0061 3 Kameari, Katsushika-ku, Tokyo-49-3 Ario Kameari 2F
En convertissant la valeur booléenne en valeur int, vous pouvez créer une colonne avec «1» dans les données contenant une certaine chaîne de caractères. Pratique pour l'ingénierie de quantité d'entités pour créer des quantités d'entités.
#Drapeau de données tokyo y compris Tokyo_Créer flg
df['tokyo_flg'] = df['address'].str.contains("Tokyo").astype(int)
df['tokyo_flg']
>> 0 1
1 1
2 1
3 0
4 0
5 0
6 1
7 1
8 0
9 1
extract Series.str.extract
--Retourne le motif correspondant.
--Retourne None
s'il n'y a pas de modèle, donc dropna ()
si pas nécessaire
--Si vous définissez un nom de groupe nommé, ce nom sera le nom de la colonne tel quel
(? P <nom> ...)
df['address'].str.extract('(Tokyo|Préfecture de Kanagawa)([^Ville de quartier]+[Ville de quartier])').dropna()
df['address'].str.extract('(?P<pref>Tokyo|Préfecture de Kanagawa)(?P<city>[^Ville de quartier]+[Ville de quartier])').dropna()
pref | city | |
---|---|---|
0 | Tokyo | Quartier Bunkyo |
1 | Tokyo | Quartier Shinjuku |
2 | Tokyo | Quartier Chiyoda |
5 | Préfecture de Kanagawa | Ville de Kamakura |
6 | Tokyo | Quartier Edogawa |
7 | Tokyo | Quartier de Toshima |
9 | Tokyo | Katsushika |
Vous pouvez créer des tables pour XX Ward à Tokyo et XX City dans la préfecture de Kanagawa.
replace
--Equivalent à re.sub ()
--Series.str.replace (pat, repl)
convertit la chaîne qui correspond à pat
en repl
#Supprimer le code postal
df['address'] = df['address'].str.replace("〒[0-9]{3}\-[0-9]{4}", "")
Au fait, Series.replace est différent de «Series.str.replace» au format dictionnaire. Peut être passé
Si vous souhaitez utiliser vos propres fonctions ou fonctions packagées (neologdn, mecab, etc.)
Utilisez Series.apply.
En passant une fonction comme Series.apply (func)
, vous pouvez exécuter le traitement de cette fonction sur les données de Series. Vous pouvez également passer une fonction lambda.
#Au début du texte'adresse de rue'Insérer
df['address'].apply(lambda x: 'adresse de rue' + x)
Le prétraitement réel du texte sera résumé ci-dessous.
neologdn 0.4
Un package de normalisation de texte japonais qui peut normaliser de longues notes et des refroidisseurs qui ne peuvent pas être traités par la bibliothèque standard Normaliser seule.
Bien sûr, avant d'analyser avec mecab Si vous l'utilisez avant d'obtenir la chaîne de caractères avec une expression régulière, l'expression régulière à écrire sera simplifiée, il est donc préférable de l'exécuter d'abord pour le texte japonais.
import neologdn
df['neologdn'] = df['address'].apply(neologdn.normalize)
#DataFrame avec fonction lambda.Vous pouvez également postuler
df['neologdn'] = df.apply(lambda x: neologdn.normalize(x['address']), axis=1)
mecab-python3
mecab-python3 0.996.3
Si vous ne voulez que le résultat de la division, spécifiez -Owakati
.
import MeCab
# `-d`Spécifiez le chemin du dictionnaire avec
tagger = MeCab.Tagger('-Owakati -d /usr/local/lib/mecab/dic/ipadic/')
df['neologdn'].apply(tagger.parse)
Dans ce cas, le dernier saut de ligne \ n
est également attaché, donc si vous souhaitez le supprimer, vous pouvez définir votre propre fonction ou utiliser l'instruction lambda.
tagger = MeCab.Tagger('-Owakati -d /usr/local/lib/mecab/dic/ipadic/')
#Définir la fonction
def my_parser(text):
res = tagger.parse(text)
return res.strip()
df['neologdn'].apply(my_parser)
#Pas besoin de déclarer une fonction avec la fonction lambda
df['neologdn'].apply(lambda x : tagger.parse(x).strip())
>>0 Kasuga 1-1, Bunkyo-ku, Tokyo-1 Bâtiment La Coeur 2 F
1 Takada Baba, Shinjuku-ku, Tokyo 1- 35 -3 Style Emio 1 F
2 Marunouchi, Chiyoda-ku, Tokyo 2- 4 -1 Bâtiment Marunouchi B 1 F
3 5-50 Misono, Midori-ku, Saitama City, Saitama Prefecture 1 Aeon Mall Urawa Misono
4 Hamacho, ville de Funabashi, préfecture de Chiba 2- 1 -1 LaLaport TOKYO-BAY LaLaport 3
5 Ofuna, ville de Kamakura, préfecture de Kanagawa 1- 4 -1 Aile Lumine 4 F
6 Minamikoiwa, Edogawa-ku, Tokyo 7- 24 -15 Chapo Koiwa 1 F
7 Minami Ikebukuro, Toyoshima-ku, Tokyo 1- 29 -1 Ikebukuro SP B 1 F
8 Wakita Town, Kawagoe City, Préfecture de Saitama 105 Atre Kawagoe 4 F
9 Kameari, Katsushika-ku, Tokyo 3- 49 -3 Ario Kameari 2 F
Sudachipy
SudachiDict-core 20190718
SudachiPy 0.4.2
Dans SudachiPy, si vous souhaitez obtenir le résultat de la division comme le mecab ci-dessus, vous devez créer une fonction qui ne renvoie que la couche de surface de l'objet de résultat d'analyse.
from sudachipy import tokenizer
from sudachipy import dictionary
tokenizer_obj = dictionary.Dictionary().create()
mode = tokenizer.Tokenizer.SplitMode.C
def sudachi_tokenize(text):
res = tokenizer_obj.tokenize(text, mode)
return ' '.join([m.surface() for m in res])
df['address'].apply(sudachi_tokenize)
>>0 1-chome, Kasuga, Bunkyo-ku, Tokyo-1 Bâtiment La Coeur 2 F
1 Takada Baba, Shinjuku-ku, Tokyo 1- 35 -3 Style Emio 1 F
2 Marunouchi, Chiyoda-ku, Tokyo 2- 4 -1 Bâtiment Marunouchi B 1 F
3 5-50 Misono, Midori-ku, Saitama City, Saitama Prefecture 1 Aeon Mall Urawa Misono
4 Hamacho, ville de Funabashi, préfecture de Chiba 2- 1 -1 LaLaport TOKYO-BAY LaLaport 3
5 Ofuna, ville de Kamakura, préfecture de Kanagawa 1- 4 -1 Aile Lumine 4 F
6 Minamikoiwa, Edogawa-ku, Tokyo 7- 24 -15 Chapo Koiwa 1 F
7 Minami Ikebukuro, Toyoshima-ku, Tokyo 1- 29 -1 Ikebukuro SP B 1 F
8 105 Wakita-cho, Kawagoe-shi, Saitama Atre Kawagoe 4 F
9 Kameari, Katsushika-ku, Tokyo 3- 49 -3 Ario Kameari 2 F
Au fait, contrairement à l'ipadic de mecab, le SplitMode.C
de Sudachi semble rassembler les adresses.
(Traitez-vous préfecture + ville / quartier / ville / village comme une expression unique?)
En plus des résultats ci-dessus
Sudachi a 3 unités séparées (Split Mode), vous pouvez donc utiliser la fonction sudachi_tokenize
pour spécifier le mode. Essayez de personnaliser.
Puisque Series.apply peut transmettre des arguments de longueur variable, vous pouvez ajouter les arguments du côté fonction et spécifier les arguments du côté appliquer.
def sudachi_tokenize_with_mode(text, mode):
res = tokenizer_obj.tokenize(text, mode)
return ' '.join([m.surface() for m in res])
df['address'].apply(sudachi_tokenize_with_mode, mode=tokenizer.Tokenizer.SplitMode.A)
>>0 Kasuga 1-1, Bunkyo-ku, Tokyo-1 Bâtiment La Coeur 2 F
1 Takada Baba, Shinjuku-ku, Tokyo 1- 35 -3 Style Emio 1 F
2 Marunouchi, Chiyoda-ku, Tokyo 2- 4 -1 Bâtiment Marunouchi B 1 F
3 5-50 Misono, Midori-ku, Saitama City, Saitama Prefecture 1 Aeon Mall Urawa Misono
4 Hamacho, ville de Funabashi, préfecture de Chiba 2- 1 -1 LaLaport TOKYO-BAY LaLaport 3
5 Ofuna, ville de Kamakura, préfecture de Kanagawa 1- 4 -1 Aile Lumine 4 F
6 Minamikoiwa, Edogawa-ku, Tokyo 7- 24 -15 Chapo Koiwa 1 F
7 Minami Ikebukuro, Toyoshima-ku, Tokyo 1- 29 -1 Ikebukuro SP B 1 F
8 Atre Kawagoe 4F, 105 Wakita-cho, Kawagoe-shi, Saitama
9 Kameari, Katsushika-ku, Tokyo 3- 49 -3 Ario Kameari 2 F
Avec SplitMode.A
, le résultat était presque le même que celui de mecab.
Sudachi a une fonction de normalisation qui modifie * simulation * en * simulation *.
Envisagez de renvoyer normalized_form
en même temps et d'en faire un DataFrame.
Puisque Series.apply
n'a pas de fonction d'expansion, essayez de l'exécuter en spécifiant result_type = 'expand'
dans DataFrame.apply
.
def sudachi_tokenize_multi(text):
res = tokenizer_obj.tokenize(text, mode)
return ' '.join([m.surface() for m in res]), ' '.join([m.normalized_form() for m in res])
df.apply(lambda x: sudachi_tokenize_multi(x['neologdn']), axis=1, result_type='expand')
0 | 1 | |
---|---|---|
0 | 1-1 Kasuga, Bunkyo-ku, Tokyo-1 Bâtiment La Coeur 2 F | 1-1 Kasuga, Bunkyo-ku, Tokyo-1 La Coeur 2 f |
1 | 1 Takada Baba, Shinjuku-ku, Tokyo- 35 -3 Style Emio 1 F | 1 Takada Baba, Shinjuku-ku, Tokyo- 35 -3 Style Emio 1 f |
2 | 2 Marunouchi, Chiyoda-ku, Tokyo- 4 -1 Bâtiment Marunouchi B 1 F | 2 Marunouchi, Chiyoda-ku, Tokyo- 4 -1 Bâtiment Marunouchi b 1 f |
3 | 5-50, Midori-ku, Saitama-shi, Saitama Aeon Mall Urawa Misono | 5-50, Midori-ku, Saitama-shi, Saitama Aeon Mall Urawa Misono |
4 | 2 Hamacho, ville de Funabashi, préfecture de Chiba- 1 -1 LaLaport TOKYO-BAY LaLaport 3 | 2 Hamacho, ville de Funabashi, préfecture de Chiba- 1 -1 LaLaport Tokyo-Baie LaLaport 3 |
5 | 1 Ofuna, ville de Kamakura, préfecture de Kanagawa- 4 -1 Aile Lumine 4 F | 1 Ofuna, ville de Kamakura, préfecture de Kanagawa- 4 -1 Aile Lumine 4 f |
6 | 7 Minamikoiwa, Edogawa-ku, Tokyo- 24 -15 Chapo Koiwa 1 F | 7 Minamikoiwa, Edogawa-ku, Tokyo- 24 -15 Shappo Koiwa 1 f |
7 | 1 Minami Ikebukuro, Toyoshima-ku, Tokyo- 29 -1 Ikebukuro SP B 1 F | 1 Minami Ikebukuro, Toyoshima-ku, Tokyo- 29 -1 Ikebukuro SP b 1 f |
8 | 105 Wakita-cho, Kawagoe-shi, Saitama Atre Kawagoe 4F | 105 Wakita-cho, Kawagoe-shi, Saitama Atre Kawagoe 4 f |
9 | 3 Kameari, Katsushika-ku, Tokyo- 49 -3 Ario Kameari 2 F | 3 Kameari, Katsushika-ku, Tokyo- 49 -3 Ario Kameari 2 f |
Dans le cas de l'adresse, je pensais que cela n'aurait aucun effet particulier, mais * Chapo * a été converti en * Shappo *, et * TOKYO --BAY * a été converti en * Tokyo --Bay *. Les caractères alphabétiques tels que F sont également inférieurs pour une raison quelconque.
Quant à l'ordre de prétraitement personnel
Cependant, si vous utilisez SudachiPy, il dispose également d'une fonction de normalisation, vous pouvez donc le tokeniser d'abord, puis supprimer ou compléter les caractères.
Comme je l'ai écrit au début, j'apprécierais que vous me disiez s'il existe une meilleure méthode de traitement.
Recommended Posts