すごい初歩的なテキストの処理作業のメモです。
Pythonのクラスに関する↓の記事を読んでいたのですが、
http://www.shido.info/py/python7.html
この記事に書かれてある「code 1」「code 2」を自分でも実行してみようと思ってコピペしようとすると、各行の先頭に数字と記号がくっついてきます。
こんな感じで。
09: def Cls(cls=None, **key): 10: """ making a new class""" 11: key['class'] = cls 12: return key
これじゃコピペで実行できないので、この先頭の数字からスペースまでをきれいに削除して普通のコードにするための処理を、RとPythonで書いてみました。
どう考えても手作業で消したほうが早いです。
Rできれいにする
何か余計な文字列を消すという処理は、どうやるのが一般的なのかとかよく分かってないんですが、検索して空情報で置換するとか、要るところと要らないところにうまく分割して要らないほうを捨てるみたいなやり方を思いつきます。
今回は、消すべき情報は全ての行の先頭に規則的に入っているわけなので、後者の方法でやってみます。
上記記事のコードを「code_1.txt」「code_2.txt」というテキストファイルにコピペした上で、以下のとおり実行。
### ↓サイトのコードから冒頭の数字の部分とかを削除したい。 ### http://www.shido.info/py/python7.html # 作業ディレクトリを指定 setwd("作業ディレクトリのpath") script.cleaning <- function (input, output) { # 元記事のコードをテキストファイルにコピペしたものをinputに与える。 # outputとして指定したpath、ファイル名で、綺麗になったものが出力される。 file <- file(input, open= "rt", encoding="utf-8") # ファイルを開く lines <- readLines(file) # テキストを読み込み close(file) # コネクションを切る # 行の冒頭の数字のところと、コードの部分をsplitする。 # コロンと空白5つが挟まっているので、これを分割記号とする。 split <- lapply(lines, function (p) { unlist(strsplit(p, ": ")) }) # 分割された各行がリストで格納されており、それぞれのコードの # 部分だけ取り出してベクトルに入れる。 vector <- c() vector <- lapply(split, function (p) { vector <- c(vector, p[2]) }) # NAとなる行(元のファイルにおける空行)を空要素に置き換える。 vector <- unlist(vector) for (i in 1:length(vector)) { if(is.na(vector[i])==TRUE) { # NAって他の方法でも指定できる? vector[i] <- c("") } } # ファイルを出力する。 output.file <- file(output, open="a") # "a"は追記モード writeLines(vector, output.file) close(output.file) } # 実行する。 script.cleaning("code_1.txt", "R_output_1.txt") script.cleaning("code_2.txt", "R_output_2.txt")
できた。
しかしなんか回りくどいことをやってる気がする。
次にPythonで書くときは、もっと普通な感じでforとかを使おうと思います。
Pythonできれいにする
次はPythonでやります。Pythonの方は、スクリプトを保存してやってみます。
同じく、上記記事のコードを「code_1.txt」「code_2.txt」というテキストファイルにコピペした上で、まず以下のスクリプトを「Script_Cleaning.py」というファイル名で保存。
#!/usr/bin/python # -*- coding: utf-8 -*- # readlinesメソッドでやる場合 def cleaning(input, output): f = open(input) lines = f.readlines() f.close() for i in range(0, len(lines)): lines[i] = lines[i].split(': ')[1] output_file = open(output, 'w') for line in lines: output_file.writelines(line) output_file.flush() output_file.close() # 参考:readメソッドでやる場合 def cleaning_2(input, output): f = open(input) d = f.read() # 行ごとではなく全体をう読み込み f.close() lines = d.split('\n') # 改行ごとに分割 for i in range(0, len(lines)-1): # 1引かないとだめだった lines[i] = lines[i].split(': ')[1] + '\n' # 改行を足す output_file = open(output, 'w') for line in lines: output_file.writelines(line) output_file.flush() output_file.close()
大きな意味はないですが2種類書きました。
テキストファイルの一番最後のところで、改行コードの後が1行分になるかならないかの違いで、readメソッドのほうでは行数の指定をマイナス1しないとダメでした。
このスクリプトを保存した上で、Pythonの対話環境下で、以下のように実行します。
>>> import Script_Cleaning >>> Script_Cleaning.cleaning('code_1.txt','py_output_1.txt') >>> Script_Cleaning.cleaning('code_2.txt','py_output_2.txt') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "Script_Cleaning.py", line 11, in cleaning lines[i] = lines[i].split(': ')[1] IndexError: list index out of range
あれ?
code 1のほうは正常にファイルが出力されましたが、code 2のほうはエラーになった。
行数が一致してないみたいな感じですが、元の記事をみてみると、code 2の48行目に改行が入っていて、ここで規則性が崩れたようだ。
46: w = 'writes programs' 47: 48: print '%s %s for %d, hours using %s on %s' % (geta(self, 'name'), w, n, geta(self, 'language'), geta(self, 'OS')) 49: 50: workers = Cls() # dummy class
よくみたらRでやった方も、code 2のほうはファイルは出力されてるけど、当該行の情報が消えていた。
めんどうなので、あとで考える。