Contents
スポンサードリンク
第2章前半の続きです。
第2章UNIXコマンドの基礎
15. 末尾のN行を出力
『自然数Nをコマンドライン引数などの手段で受け取り,入力のうち末尾のN行だけを表示せよ.確認にはtailコマンドを用いよ』
1 2 3 4 5 6 7 8 9 |
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys hoge = sys.argv[2] with open(sys.argv[1]) as f: lines = f.readlines() for line in lines[len(lines)-int(hoge):len(lines)]: print (line) |
ここまでの知識でできる問題です。特に難しくないです。コマンドライン引数で指定した、数字をhogeとして受け取りそれを使うだけです。
実行結果(コマンドライン引数に6を入力した場合):
1 |
$ python ファイル名.py hightemp.txt 6 |
1 2 3 4 5 6 7 8 9 10 11 |
千葉県 茂原 39.9 2013年8月11日 ○ 埼玉県 鳩山 39.9 1997年7月5日 ○ 大阪府 豊中 39.9 1994年8月8日 ○ 山梨県 大月 39.9 1990年7月19日 ○ 山形県 鶴岡 39.9 1978年8月3日 ○ 愛知県 名古屋 39.9 1942年8月2日 ○ |
UNIXコマンドでの確認:
1 |
tail -6 hightemp.txt |
数字の前に- をつけましょう。
16. ファイルをN分割する
『自然数Nをコマンドライン引数などの手段で受け取り,入力のファイルを行単位でN分割せよ.同様の処理をsplitコマンドで実現せよ.』
コマンドライン引数を用いない場合:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#!/usr/bin/env python # -*- coding: utf-8 -*- import math fname = 'hightemp.txt' n = int(input('N--> ')) with open(fname) as data_file: lines = data_file.readlines() count = len(lines) unit = math.ceil(count / n) # 1ファイル当たりの行数 for i, offset in enumerate(range(0, count, unit), 1): with open('child_{:02d}.txt'.format(i), mode='w') as out_file: for line in lines[offset:offset + unit]: out_file.write(line) |
input関数は、コマンドラインで入力したデータを文字列として扱うものです。そして入力した文字列をしようし、プログラム内で用いることができます。
math.ceil()は切り上げです。4/3でしたら、1.3333 となり四捨五入なら1となりますが、切り上げなので2になります。
コマンドライン引数を用いる場合:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#!/usr/bin/env python # -*- coding: utf-8 -*- import math import sys hoge = sys.argv[2] with open(sys.argv[1]) as f: lines = f.readlines() count = len(lines) unit = math.ceil(count / int(hoge)) # 1ファイル当たりの行数 for i, offset in enumerate(range(0, count, unit), 1): with open('child_{:02d}.txt'.format(i), mode='w') as out_file: for line in lines[offset:offset + unit]: out_file.write(line) |
ファイル分割数を2番目のコマンドライン引数で入力した場合のやり方です。
分割の入力方法が異なるので、unitの指定の仕方が少し異なるだけです。これまでの知識のみで書けます。
実行結果(分割数が4の場合):
1 |
$python ファイル名.py hightemp.txt 4 |
上を実行すると、child_0*のファイルが作成されます。ここでは4分割されたファイルのうち一つのファイルの中身を示します。
unitで計算している通り、行数が (hightemp.txtの行数/分割数)になっていれば良いはずです。
1 2 3 4 5 6 |
高知県 江川崎 41.0 2013年8月12日 ○ 埼玉県 熊谷 40.9 2007年8月16日 ○ 岐阜県 多治見 40.9 2007年8月16日 ○ 山形県 山形 40.8 1933年7月25日 ○ 山梨県 甲府 40.7 2013年8月10日 ○ 和歌山 かつらぎ 40.6 1994年8月8日 ○ |
24/4=6なので成功です。
UNIXコマンドでの確認:
1 |
split -l 4 hightemp.txt out. |
out.*でファイルが作成されます。
注意しなければならないのは、ここでの4は分割数ではなくsplitの数(何行ごとに分割するかの数)なので、24/4=6となり、ファイルが6つ作成されるはずです。
17. 1列目の文字列の異なり
『1列目の文字列の種類(異なる文字列の集合)を求めよ.確認にはsort, uniqコマンドを用いよ.』
1 2 3 4 5 6 7 8 9 |
#!/usr/bin/env python # -*- coding: utf-8 -*- hoge = set() with open('hightemp.txt', 'r') as f: for line in f: elements = line.rstrip().split('\t') for line in elements[0]: hoge.add(elements[0]) print(hoge) |
最初まず問題の意味を理解するのに苦労しました笑。要するに24つのデータのうち、何県のデータかということです。県がダブっているデータもあるので、そういうのをダブりでカウントしないようにするにはどうすれば良いかということです。
set()コマンドで一発。そうすることで、list型のデータが集合型 に置き替わります。
データを集合として扱う場合,このsetコマンドはかなり重宝されます。
実行結果:
1 |
{'高知県', '愛知県', '愛媛県', '埼玉県', '静岡県', '山形県', '群馬県', '大阪府', '千葉県', '和歌山 かつらぎ 40.6 1994年8月8日', '岐阜県', '山梨県'} |
相変わらず和歌山県のところだけおかしいですが、hightemp.txtの問題なので、無視します笑
UNIXコマンドでの確認:
1 |
cut -f 1 hightemp.txt | sort | uniq |
uniqは連続して重複している行を一つにまとまるコマンドで、sortは辞書順に並び替えてくれるものです。
離れたデータの重複を一つにまとめる時は両方を組み合わせます。二つのコマンドを組み合すことで、かなり便利なものになりますね。
スポンサードリンク
18. 各行を3コラム目の数値の降順にソート
『各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ).確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい)』
1 2 3 4 5 6 7 |
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys with open(sys.argv[1]) as f: lines = f.readlines() for line in sorted(lines, key=lambda x: x.split()[2], reverse=True): print (line) |
温度の高い順にデータを並び替えろということです。
無名関数(lambda)を使っています。
無名関数は「その場限りの関数」で自在に使えればかなり柔軟なプログラムがかけます。
オーダーメイドのスーツを作っても、自分以外の人にとっては無意味なイメージです。ただし、自分にとってはちょーぜつ大事ですよね。
sorted()でデータを並び替えますが、その並び替え方をlambdaを使って指定しています。
数学チックに説明すると、xは変数です。このxにいろんな値が入ります。今なら各行のデータです。1行目も、2行目も、3行目もこの.split()[2]を使います、という意味です。
.split()[2]はこれまでの知識で理解できますね。分割したデータ集合のうち3番目のデータ(list型は0から始まります。)、すなわち温度のデータに注目してデータを sort(並び替えましょう)という意味です。
最後に「数値の逆順」と言っているので、reverse=Trueと書きます。
実行結果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
高知県 江川崎 41.0 2013年8月12日 ○ 埼玉県 熊谷 40.9 2007年8月16日 ○ 岐阜県 多治見 40.9 2007年8月16日 ○ 山形県 山形 40.8 1933年7月25日 ○ 山梨県 甲府 40.7 2013年8月10日 ○ 和歌山 かつらぎ 40.6 1994年8月8日 ○ 静岡県 天竜 40.6 1994年8月4日 ○ 山梨県 勝沼 40.5 2013年8月10日 ○ 埼玉県 越谷 40.4 2007年8月16日 ○ 群馬県 館林 40.3 2007年8月16日 ○ 群馬県 上里見 40.3 1998年7月4日 ○ 愛知県 愛西 40.3 1994年8月5日 ○ 千葉県 牛久 40.2 2004年7月20日 ○ 静岡県 佐久間 40.2 2001年7月24日 ○ 愛媛県 宇和島 40.2 1927年7月22日 ○ 山形県 酒田 40.1 1978年8月3日 ○ 岐阜県 美濃 40.0 2007年8月16日 ○ 群馬県 前橋 40.0 2001年7月24日 ○ 千葉県 茂原 39.9 2013年8月11日 ○ 埼玉県 鳩山 39.9 1997年7月5日 ○ 大阪府 豊中 39.9 1994年8月8日 ○ 山梨県 大月 39.9 1990年7月19日 ○ 山形県 鶴岡 39.9 1978年8月3日 ○ 愛知県 名古屋 39.9 1942年8月2日 ○ |
温度の高い順になっているのがわかります。
UNIXコマンドでの確認:
1 |
sort -r -k 3 hightemp.txt |
pythonプログラムと実行結果が異なると思います。
19. 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる
『各行の1列目の文字列の出現頻度を求め,その高い順に並べて表示せよ.確認にはcut, uniq, sortコマンドを用いよ.』
1 2 3 4 5 6 7 8 9 10 11 |
#!/usr/bin/env python # -*- coding: utf-8 -*- from collections import Counter hoge = [] with open('hightemp.txt', 'r') as f: for line in f: elements = line.rstrip().split('\t') hoge.append(elements[0]) counter = Counter(hoge) for word, cnt in counter.most_common(): print (word, cnt) |
listデータの出現回数を求めるのはcollectionsライブラリのCounter()コマンドで数えることが可能です。
単語と単語の出現回数を表示させるにはcounterに格納されているデータを用いるのですが、その際に.most_common()という引数を用います。決まり文句として覚えて構わないでしょう。
出力するのは単語(県名)とその出現数なので、for文の変数を二つ指定します。
実行結果:
1 2 3 4 5 6 7 8 9 10 11 12 |
埼玉県 3 山形県 3 山梨県 3 群馬県 3 岐阜県 2 静岡県 2 愛知県 2 千葉県 2 高知県 1 和歌山 かつらぎ 40.6 1994年8月8日 1 愛媛県 1 大阪府 1 |
UNIXコマンドでの確認:
1 |
cut -f 1 hightemp.txt | sort | uniq -c | sort -r |
uniq -c で重複行をカウントしてくれるみたいです。
| sort -r なしで実行すると、カウントはしてくれますが、出現回数の多い順に並び替えされないので、いります。
最初のsortはあくまでuniqで重複行をカウントするためのものです。(uniqは縦に連続したデータの重複を数えるから。県名が同じでも離れたデータであれば、別に別にカウントしてしまいます。)
以上で2章は終了です。続きはこちら→3章前半!
スポンサードリンク