今日から第2章。
これの続きでーす。
Python未経験者が言語処理100本ノックをやってみる07~09
https://qiita.com/earlgrey914/items/a7b6781037bc0844744b
第1章で「7時間かかった」と言ったら「仕事は?」と言われました。
もちろんしてますeん。
下準備
hightemp.txtは,日本の最高気温の記録を「都道府県」「地点」「℃」「日」のタブ区切り形式で格納したファイルである.以下の処理を行うプログラムを作成し,hightemp.txtを入力ファイルとして実行せよ.さらに,同様の処理をUNIXコマンドでも実行し,プログラムの実行結果を確認せよ.
このhightemp.txtを入力ファイルとして
・処理を行うPythonプログラムを書く
・UNIXコマンドでも同様の処理(コマンド実行)をしてみる
ってのが第2章の内容みたいです。
hightemp.txtの中身はこんな感じ。
タブ区切りの24行4列のデータ。
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
山形県 山形 40.8 1933-07-25
山梨県 甲府 40.7 2013-08-10
和歌山県 かつらぎ 40.6 1994-08-08
静岡県 天竜 40.6 1994-08-04
山梨県 勝沼 40.5 2013-08-10
埼玉県 越谷 40.4 2007-08-16
群馬県 館林 40.3 2007-08-16
群馬県 上里見 40.3 1998-07-04
愛知県 愛西 40.3 1994-08-05
千葉県 牛久 40.2 2004-07-20
静岡県 佐久間 40.2 2001-07-24
愛媛県 宇和島 40.2 1927-07-22
山形県 酒田 40.1 1978-08-03
岐阜県 美濃 40 2007-08-16
群馬県 前橋 40 2001-07-24
千葉県 茂原 39.9 2013-08-11
埼玉県 鳩山 39.9 1997-07-05
大阪府 豊中 39.9 1994-08-08
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02
私はPython実行環境としてAWS Cloud9を利用していますので、
そちらに本txtファイルをアップしてから開始です。
余談ですけど、Cloud9は本当に便利ですね。
Cloud9でネイティブGUIアプリの開発もできると嬉しいなぁと思ってます(おかしな事を言っている)
10. 行数のカウント
行数をカウントせよ.確認にはwcコマンドを用いよ.
えーと。まずPythonでtxtファイルを読み込む方法っと。
これは知ってる。.pyと同じところに.txtを置いてるからこれで大丈夫でしょう。
with open('hightemp.txt') as f:
s = f.read()
print(s)
Traceback (most recent call last):
File "/home/ec2-user/knock/02/enshu11.py", line 6, in <module>
with open('hightemp.txt') as f:
FileNotFoundError: [Errno 2] No such file or directory: 'hightemp.txt'
あらー。ダメなのね。
~3分ほどググる~
<参考URL>
https://qiita.com/nagamee/items/b7d1b02074293fdfdfff
import os.path
#このpyファイルのある場所を原点とする
os.chdir((os.path.dirname(os.path.abspath(__file__))))
with open('hightemp.txt') as f:
s = f.read()
print(s)
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
:
これでOK。
このos.chdir((os.path.dirname(os.path.abspath(__file__))))
のおまじない?は今後も書いていっていいものなのだろうか?
実行環境によって必要だったり不要(というか書いてはダメ)だったりしそう・・・
で、ファイルをopen()
したあとにどういった形で中身を読み込むかはいくつかやり方があるようだ。
今回の問題では「行数をカウントせよ」とのことなので、行単位でリストにしてくれるreadlines()
を使うのがいいだろう。
import os.path
#このpyファイルのある場所を原点とする
os.chdir((os.path.dirname(os.path.abspath(__file__))))
with open('hightemp.txt') as f:
s = f.readlines()
print(len(s))
24
簡単でござる。
UNIXコマンドでも同じことをしろとのことなので実行。
[ec2-user@ip-172-31-34-215 02]$ wc -l hightemp.txt
24 hightemp.txt
ファイル名が邪魔だな。
catをかまそう。
[ec2-user@ip-172-31-34-215 02]$ cat hightemp.txt | wc -l
24
11. タブをスペースに置換
タブ1文字につきスペース1文字に置換せよ.確認にはsedコマンド,trコマンド,もしくはexpandコマンドを用いよ.
なんか1章より簡単じゃない?
import os.path
os.chdir((os.path.dirname(os.path.abspath(__file__))))
with open('hightemp.txt', mode="r") as f:
s = f.read()
tikango = s.replace("\t", " ")
with open('hightemp.txt', mode="w") as f:
f.write(tikango)
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
山形県 山形 40.8 1933-07-25
山梨県 甲府 40.7 2013-08-10
和歌山県 かつらぎ 40.6 1994-08-08
静岡県 天竜 40.6 1994-08-04
山梨県 勝沼 40.5 2013-08-10
埼玉県 越谷 40.4 2007-08-16
群馬県 館林 40.3 2007-08-16
群馬県 上里見 40.3 1998-07-04
愛知県 愛西 40.3 1994-08-05
千葉県 牛久 40.2 2004-07-20
静岡県 佐久間 40.2 2001-07-24
愛媛県 宇和島 40.2 1927-07-22
山形県 酒田 40.1 1978-08-03
岐阜県 美濃 40 2007-08-16
群馬県 前橋 40 2001-07-24
千葉県 茂原 39.9 2013-08-11
埼玉県 鳩山 39.9 1997-07-05
大阪府 豊中 39.9 1994-08-08
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02
ターミナルでもsedで置換してみる。
[ec2-user@ip-172-31-34-215 02]$ sed -i -e "s/\t/ /g" hightemp.txt
[ec2-user@ip-172-31-34-215 02]$ cat hightemp.txt
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
山形県 山形 40.8 1933-07-25
山梨県 甲府 40.7 2013-08-10
和歌山県 かつらぎ 40.6 1994-08-08
静岡県 天竜 40.6 1994-08-04
山梨県 勝沼 40.5 2013-08-10
埼玉県 越谷 40.4 2007-08-16
群馬県 館林 40.3 2007-08-16
群馬県 上里見 40.3 1998-07-04
愛知県 愛西 40.3 1994-08-05
千葉県 牛久 40.2 2004-07-20
静岡県 佐久間 40.2 2001-07-24
愛媛県 宇和島 40.2 1927-07-22
山形県 酒田 40.1 1978-08-03
岐阜県 美濃 40 2007-08-16
群馬県 前橋 40 2001-07-24
千葉県 茂原 39.9 2013-08-11
埼玉県 鳩山 39.9 1997-07-05
大阪府 豊中 39.9 1994-08-08
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-0
12. 1列目をcol1.txtに,2列目をcol2.txtに保存
各行の1列目だけを抜き出したものをcol1.txtに,2列目だけを抜き出したものをcol2.txtとしてファイルに保存せよ.確認にはcutコマンドを用いよ.
なんか一気に簡単になってしまいやる気減。
import os.path
os.chdir((os.path.dirname(os.path.abspath(__file__))))
with open('hightemp.txt', mode="r") as f:
linedata = f.readlines()
for l in linedata:
with open('col1.txt', mode="a") as c1:
c1.write(l.split(" ")[0] + "\r")
with open('col2.txt', mode="a") as c2:
c2.write(l.split(" ")[1] +"\r")
高知県
埼玉県
岐阜県
山形県
山梨県
和歌山県
静岡県
山梨県
埼玉県
群馬県
群馬県
愛知県
千葉県
静岡県
愛媛県
山形県
岐阜県
群馬県
千葉県
埼玉県
大阪府
山梨県
山形県
愛知県
江川崎
熊谷
多治見
山形
甲府
かつらぎ
天竜
勝沼
越谷
館林
上里見
愛西
牛久
佐久間
宇和島
酒田
美濃
前橋
茂原
鳩山
豊中
大月
鶴岡
名古屋
cutコマンドはこうでしょ。
[ec2-user@ip-172-31-34-215 02]$ cut -f 1 -d " " hightemp.txt > col1_command.txt
[ec2-user@ip-172-31-34-215 02]$ cut -f 2 -d " " hightemp.txt > col2_command.txt
diffで比較っと・・・
[ec2-user@ip-172-31-34-215 02]$ diff col1.txt col1_command.txt
1c1,24
愛知県県
\ No newline at end of file
---
> 高知県
> 埼玉県
> 岐阜県
> 山形県
> 山梨県
> 和歌山県
> 静岡県
> 山梨県
> 埼玉県
> 群馬県
> 群馬県
> 愛知県
> 千葉県
> 静岡県
> 愛媛県
> 山形県
> 岐阜県
> 群馬県
> 千葉県
> 埼玉県
> 大阪府
> 山梨県
> 山形県
> 愛知県
アレッ!?
cat col1.txt
でも表示されないからこれは・・・
改行コードのせいだ!
ということで改行コードを\r
から\n
に変え、ファイル書き込み時のエンコードもUTF-8
を指定しました。
import os.path
os.chdir((os.path.dirname(os.path.abspath(__file__))))
with open('hightemp.txt', mode="r") as f:
linedata = f.readlines()
for l in linedata:
with open('col1.txt', mode="a", encoding="utf-8") as c1:
c1.write(l.split(" ")[0] + "\n")
with open('col2.txt', mode="a", encoding="utf-8") as c2:
c2.write(l.split(" ")[1] +"\n")
実行確認
[ec2-user@ip-172-31-34-215 02]$ python3 enshu12.py
[ec2-user@ip-172-31-34-215 02]$
[ec2-user@ip-172-31-34-215 02]$ cut -f 1 -d " " hightemp.txt > col1_command.txt
[ec2-user@ip-172-31-34-215 02]$ cut -f 2 -d " " hightemp.txt > col2_command.txt
[ec2-user@ip-172-31-34-215 02]$ diff col1.txt col1_command.txt
[ec2-user@ip-172-31-34-215 02]$ diff col2.txt col2_command.txt
[ec2-user@ip-172-31-34-215 02]$
おっけーでーす。
13. col1.txtとcol2.txtをマージ
12で作ったcol1.txtとcol2.txtを結合し,元のファイルの1列目と2列目をタブ区切りで並べたテキストファイルを作成せよ.確認にはpasteコマンドを用いよ.
たぶんこんな感じでいけるけど、もっといいやり方ないかしら?
with open col1.txt
すべての行を配列1に入れる
with open col2.txt
すべての行を配列2に入れる
for[i]
出力ファイル = write(配列1[i] + "\t" + 配列2[i])
~20分後~
import os.path
os.chdir((os.path.dirname(os.path.abspath(__file__))))
linedata_col1 = []
linedata_col2 = []
with open('col1.txt', mode="r") as f:
linedata_col1 = f.read().splitlines()
with open('col2.txt', mode="r") as f:
linedata_col2 = f.read().splitlines()
with open('merge.txt', mode="a", encoding="utf-8") as f:
for c1, c2 in zip(linedata_col1, linedata_col2):
f.write(c1 + "\t" + c2 + "\n")
高知県 江川崎
埼玉県 熊谷
岐阜県 多治見
山形県 山形
山梨県 甲府
和歌山県 かつらぎ
静岡県 天竜
山梨県 勝沼
埼玉県 越谷
群馬県 館林
群馬県 上里見
愛知県 愛西
千葉県 牛久
静岡県 佐久間
愛媛県 宇和島
山形県 酒田
岐阜県 美濃
群馬県 前橋
千葉県 茂原
埼玉県 鳩山
大阪府 豊中
山梨県 大月
山形県 鶴岡
愛知県 名古屋
工夫ポイントはlinedata_col1 = f.read().splitlines()
です。
f.readlines()
で1行ずつ読み込むのもアリなんだけど、それだと↓のように改行コード込みのリストになってしまいます。
with open('col1.txt', mode="r") as f:
linedata_col1 = f.readlines()
print(linedata_col1)
['高知県\n', '埼玉県\n', '岐阜県\n', '山形県\n', '山梨県\n', '和歌山県\n', '静岡県\n', '山梨県\n', '埼玉県\n', '群馬県\n', '群馬県\n', '愛知県\n', '千葉県\n', '静岡県\n', '愛媛県\n', '山形県\n', '岐阜県\n', '群馬県\n', '千葉県\n', '埼玉県\n', '大阪府\n', '山梨県\n', '山形県\n', '愛知県\n']
この改行コードをわざわざ消すくらいなら、read()
で改行コード込みでブロックオブジェクトとして読み込み、改行コードでsplit()
してリスト化するのがベストだと思いました。
ではpasteとの比較。
[ec2-user@ip-172-31-34-215 02]$ python3 enshu13.py
[ec2-user@ip-172-31-34-215 02]$ paste col1.txt col2.txt > merge_command.txt
[ec2-user@ip-172-31-34-215 02]$ diff merge.txt merge_command.txt
[ec2-user@ip-172-31-34-215 02]$
なんだか簡単かつ、ファイルを挟むので結果検証が面倒になってきたぞ。
続きは明日にしよ~かな~
ここまで2時間かかりました!!ダラダラやってなので今回はあまり参考にならないかと。