Knock 100 language processing publié sur la page Web du laboratoire Inui-Okazaki de l'Université de Tohoku pour la formation au traitement du langage naturel et Python. Je vais contester nlp100 /). Je prévois de prendre note du code implémenté et des techniques à supprimer. Le code sera également publié sur GitHub.
Ceci est une suite du Chapitre 1.
Seulement ici, je pense qu'il serait bon d'insérer une petite explication des commandes UNIX ainsi que Python.
Pour les options détaillées des commandes UNIX, consultez la commande man
ou le site Web d'ITpro, et vous l'apprendrez correctement!
hightemp.txt est un fichier qui stocke l'enregistrement de la température la plus élevée au Japon dans le format délimité par des tabulations de «préfecture», «point», «℃» et «jour». Créez un programme qui effectue le traitement suivant et exécutez hightemp.txt en tant que fichier d'entrée. De plus, exécutez le même processus avec une commande UNIX et vérifiez le résultat de l'exécution du programme.
Comptez le nombre de lignes. Utilisez la commande wc pour confirmation.
10.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 10.py
import sys
f = open(sys.argv[1])
lines = f.readlines()
print(len(lines))
f.close()
Puisque l'énoncé du problème dit "hightemp.txt comme fichier d'entrée", je l'ai conçu pour qu'il puisse prendre des arguments de ligne de commande en utilisant sys.argv
.
Au moment de l'exécution, il est réglé sur $ python 10.py high temp.txt
, donc dans ce cas sys.argv [0] ==" 10.py "
, sys.argv [1] ==" hightemp.txt "
Cela signifie que la chaîne de caractères est stockée.
Concernant la lecture des fichiers
f = open (nom de fichier)
hoge = f.read() / f.readline() / f.readlines()
f.close()
J'irai avec le courant. Les trois types de fonctions qui apparaissent dans 2 . Se comportent comme suit. Veuillez utiliser correctement si nécessaire.
read()
readline()
readline ()
soit exécuté à chaque fois que vous bouclez. En dehors de cela, read () / readlines ()
est lu en une seule fois, c'est donc recommandé lorsque vous voulez quitter quand un gros fichier ou des conditions sont remplies.readlines()
len ()
).avec
Pour lire (écrire) un fichier, il existe une méthode d'écriture qui utilise «with» en plus de la méthode d'écriture qui implique «close ()» comme décrit ci-dessus. Il semble que cela soit recommandé pour éviter d'oublier d'ajouter close ()
et d'oublier de gérer les exceptions, qui sont courantes lors de l'utilisation de with
.
Le programme suivant est une réécriture d'essai de 10.py
using with
.
Lors de l'utilisation de la syntaxe with
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# 10.py
import sys
with open(sys.argv[1]) as f:
lines = f.readlines()
print(len(lines))
Après cela, en principe, utilisez with
pour lire et écrire des fichiers. Seulement si vous ne pouvez pas écrire avec with
(y a-t-il?), Programmez à l'ancienne.
$ wc -l hightemp.txt
24 hightemp.txt
La commande wc
affichera le nombre de lignes, de mots et d'octets dans le fichier.
Si aucune option n'est spécifiée, elle sera sortie dans l'ordre suivant.
$ wc hightemp.txt
24 98 813 hightemp.txt
Les options sont «-l» pour le nombre de lignes, «-w» pour le nombre de mots et «-c» pour le nombre d'octets.
Remplacez chaque onglet par un espace. Utilisez la commande sed, la commande tr ou la commande expand pour confirmation.
11.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 11.py
import sys
with open(sys.argv[1]) as f:
str = f.read()
print(str.replace("\t", " "))
Contrairement au précédent qui se concentrait sur les lignes, cette fois je veux juste remplacer les caractères à la fois, donc j'utilise simplement read ()
.
La fonction replace ()
apparue dans le chapitre précédent remplace le caractère de tabulation (\ t
) par un espace.
~~ Je n'aime pas les sauts de ligne supplémentaires laissés à la fin du résultat de sortie, mais c'est assez mignon ...? ~~
Par défaut, print ()
aura un saut de ligne à la fin. Pour éviter cela, dans Python 2, vous pouvez ajouter une virgule à la fin, comme print" hogehoge ",
. Dans Python 3, vous pouvez spécifier le caractère à ajouter à la fin avec ʻend, tel que
print ("hogehoge", end = "") , ainsi vous pouvez spécifier
" "`.
//version sed (notez que cela dépend de l'environnement)
$ sed -e s/$'\t'/" "/g hightemp.txt
// tr version
$ cat hightemp.txt | tr "\t" " "
// expand version
$ expand -t 1 hightemp.txt
//le résultat est le même
Préfecture de Kochi Egawasaki 41 2013-08-12
40 Kumagai, Préfecture de Saitama.9 2007-08-16
40 Tajimi, Préfecture de Gifu.9 2007-08-16
(Omis...)
Otsuki, Yamanashi 39.9 1990-07-19
39 Tsuruoka, Préfecture de Yamagata.9 1978-08-03
Préfecture d'Aichi Nagoya 39.9 1942-08-02
sed
est une commande pratique qui peut gérer diverses modifications de caractères, mais à des fins limitées (remplacement de caractères) comme cette fois, il serait sage d'utiliser la commande ( tr
) à cette fin.
Au contraire, «développer» a des utilisations trop limitées, vous n'aurez donc peut-être pas la chance de le toucher.
sed
-e
et décrivez le traitement que vous souhaitez effectuer par la suite, le résultat sera affiché sur la sortie standard. La notation peut être unique, mais elle peut être familière aux utilisateurs de Vim.tr
expand
-t
.Enregistrez uniquement la première colonne de chaque ligne sous col1.txt et la deuxième colonne sous col2.txt. Utilisez la commande cut pour confirmation.
12.py
#! /usr/bin/env python
# -*- coding:utf-8 -*-
# 12.py
import sys
def write_col(source_lines, colunm_number, filename):
col = []
for line in source_lines:
col.append(line.split()[colunm_number] + "\n")
with open(filename, "w") as writer:
writer.writelines(col)
with open(sys.argv[1]) as f:
lines = f.readlines()
write_col(lines, 0, "col1.txt")
write_col(lines, 1, "col2.txt")
J'en ai fait une fonction car il effectue un traitement similaire. Écrit la ligne spécifiée dans le 2ème argument de la liste
reçue dans le 1er argument comme nom de fichier du 3ème argument. ʻAppend () `ajoute un caractère de saut de ligne pour améliorer l'apparence.
Je n'utilise aucune nouvelle technologie, je peux donc en parler beaucoup, mais je suis gêné que les algorithmes soient différents selon le programme ... Les détails seront décrits plus tard, mais ils sont affichés tels quels pour réflexion.
$ cut -f 1 hightemp.txt
Préfecture de Kochi
Saitama
Préfecture de Gifu
(Omis...)
Préfecture de Yamanashi
Préfecture de Yamagata
Préfecture d'Aichi
$ cut -f 2 hightemp.txt
Egawazaki
Kumagai
Tajimi
(Omis...)
Otsuki
Tsuruoka
Nagoya
Comme avec Python, ce que nous faisons est de spécifier des champs (lignes) avec -f
. Notez qu'en Python, il était basé sur zéro (ligne 0, ligne 1 ...), alors que dans les commandes UNIX, il était basé sur un (ligne 1, ligne 2 ...).
Combinez les col1.txt et col2.txt créés dans 12 pour créer un fichier texte dans lequel les première et deuxième colonnes du fichier d'origine sont disposées en tabulation. Utilisez la commande coller pour confirmation.
13.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 13.py
with open("col1.txt") as f1, open("col2.txt") as f2:
lines1, lines2 = f1.readlines(), f2.readlines()
with open("merge.txt", "w") as writer:
for col1, col2 in zip(lines1, lines2):
writer.write("\t".join([col1.rstrip(), col2]))
Je m'habitue à Python, j'ai donc écrit la première moitié de la partie lecture avec un peu de familiarité. C'est fort de pouvoir écrire comme ça.
Pour la partie d'écriture dans la seconde moitié, j'ai essayé d'écrire en utilisant zip ()
comme révision du chapitre 1. Contrairement à 12., cette fois les deux caractères de saut de ligne restent à la fin de «col1 et col2», donc le caractère de saut de ligne à la fin de «col1» est supprimé par «rstrip ()».
Voici une revue et réécrit dans la notation d'inclusion.
Une fois réécrit par la notation d'inclusion
#S'il est entre parenthèses, il sera interprété correctement même si un saut de ligne se produit dans le code
with open("merge.txt", "w") as writer:
writer.write(
"\n".join(
["\t".join([col1.rstrip(), col2.rstrip()])
for col1, col2 in zip(lines1, lines2)]
)
)
Depuis que diverses notations sont sorties, j'ai mesuré et comparé le temps d'exécution de chaque méthode en utilisant timeit
.
Programme de mesure du temps d'exécution avec timeit
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 13_timeit.py
import timeit
#Prétraitement; col1,col2.Lire txt
s0 = """
with open("col1.txt") as f1, open("col2.txt") as f2:
lines1, lines2 = f1.readlines(), f2.readlines()
"""
#mise en œuvre naïve;Ajouter des chaînes
s1 = """
merged_txt = ""
for i in xrange(len(lines1)):
merged_txt = merged_txt + lines1[i].rstrip() + "\t" + lines2[i]
with open("merge.txt", "w") as writer:
writer.write(merged_txt)
"""
#Implémentation avec zip
s2 = """
with open("merge.txt", "w") as writer:
for col1, col2 in zip(lines1, lines2):
writer.write("\t".join([col1.rstrip(), col2]))
"""
#Notation d'inclusion(connotation)Mise en œuvre par
# "\\n"Si vous n'écrivez pas, vous obtiendrez SyntaxError ... pourquoi?
s3 = """
with open("merge.txt", "w") as writer:
writer.write(
"\\n".join(
["\t".join([col1.rstrip(), col2.rstrip()])
for col1, col2 in zip(lines1, lines2)]
)
)
"""
print("naive:", timeit.repeat(stmt=s1, setup=s0, number=100000))
print("zip:", timeit.repeat(stmt=s2, setup=s0, number=100000))
print("connotation:", timeit.repeat(stmt=s3, setup=s0, number=100000))
C'est le temps de calcul (en secondes) lorsque 100 000 tours de boucle sont effectués 3 fois (par défaut) par 3 types de méthodes. Selon le Document officiel, le temps d'exécution doit être évalué par la valeur minimale et non par la valeur moyenne ou maximale.
Résultat d'exécution
$ python 13_timeit.py
('naive:', [32.61601686477661, 47.96871089935303, 33.15881299972534])
('zip:', [49.846755027770996, 45.05450105667114, 58.70397615432739])
('connotation:', [46.472286224365234, 52.708040952682495, 46.71139121055603])
En conséquence, en termes de temps d'exécution uniquement, la méthode consistant simplement à ajouter des chaînes de caractères était la meilleure. Même si l'ordre est changé. En général, il semble que l'on puisse s'attendre à une accélération avec la notation d'inclusion, mais quelle est la frontière entre l'accélération et la non-accélération?
$ paste col1.txt col2.txt
Préfecture de Kochi Egawazaki
Kumagai, Préfecture de Saitama
Tajimi, préfecture de Gifu
(Omis...)
Préfecture de Yamanashi Otsuki
Tsuruoka, préfecture de Yamagata
Préfecture d'Aichi Nagoya
La commande paste
concatène les fichiers horizontalement.
Tab est le délimiteur par défaut, mais il peut être spécifié avec l'option -d
.
Recevoir le nombre naturel N au moyen d'un argument de ligne de commande et afficher uniquement les N premières lignes de l'entrée. Utilisez la commande head pour confirmation.
14.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 14.py
# Usage: python 14.py [filename] [number of lines]
import sys
with open(sys.argv[1]) as f:
lines = f.readlines()
for line in lines[:int(sys.argv[2])]:
print line,
Au début, j'ai utilisé l'implémentation suivante en utilisant xrange ()
, mais
xrange()Implémentation utilisant
#Omission
for i in xrange(int(sys.argv[2])):
print lines[i],
Si vous faites cela, ʻIndexErrorapparaîtra lorsque vous spécifiez un nombre qui dépasse le nombre de lignes dans le fichier, donc je pense qu'il serait sage d'implémenter en utilisant des tranches. Je pense que le problème est que la valeur d'entrée n'est pas vérifiée et que la gestion des erreurs n'est pas écrite en premier lieu ... Concernant la sortie, comme expliqué en 11., nous avons ajouté
,à la fin de l'instruction
print` pour supprimer les sauts de ligne inutiles.
$ head -3 hightemp.txt
Préfecture de Kochi Egawasaki 41 2013-08-12
40 Kumagai, Préfecture de Saitama.9 2007-08-16
40 Tajimi, Préfecture de Gifu.9 2007-08-16
C'est également simple, vous pouvez spécifier le nombre de lignes en option.
Recevoir le nombre naturel N au moyen d'un argument de ligne de commande et n'afficher que les N dernières lignes de l'entrée. Utilisez la commande tail pour confirmation.
15.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 15.py
import sys
with open(sys.argv[1]) as f:
lines = f.readlines()
for line in lines[len(lines) - int(sys.argv[2]):]:
print line,
C'est presque le même que les 14 précédents. Bien que la spécification de tranche soit légèrement compliquée.
$ tail -3 hightemp.txt
Otsuki, Yamanashi 39.9 1990-07-19
39 Tsuruoka, Préfecture de Yamagata.9 1978-08-03
Préfecture d'Aichi Nagoya 39.9 1942-08-02
Presque la même chose que «head».
Comme il est devenu long, j'ai divisé l'article sur le chapitre 2. Passez au chapitre 2, partie 2.
Recommended Posts