StatsBeginner: 初学者の統計学習ノート

初学者が統計学、機械学習、R、Pythonの勉強の過程をメモっていくノート。

【作業メモ】テキストファイルの行の先頭の記号を消したい(RとPython)

 すごい初歩的なテキストの処理作業のメモです。


 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")


 できた。


f:id:midnightseminar:20151026154518p:plain


 しかしなんか回りくどいことをやってる気がする。
 次に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のほうはファイルは出力されてるけど、当該行の情報が消えていた。


f:id:midnightseminar:20151026154539p:plain


 めんどうなので、あとで考える。