2章です
コードはgithubにあげるようにしました。
今回の範囲で使うテキストファイルは以下
高知県 江川崎 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
10. 行数のカウント
行数をカウントせよ.確認にはwcコマンドを用いよ.
# リスト内包表記使ってみる
num_lines = len([line for line in open('./hightemp.txt')])
print(num_lines)
# 結果確認用
import subprocess
output = subprocess.check_output(['wc','-l','./hightemp.txt'])
print(output)
コード実行結果とコマンド実行結果
10実行結果
$ python 10.py
24
b'24 ./hightemp.txt\n'
1章終わったあとに他の人のコード見たらfor文短い!と思って
調べてたらリスト内包表記なんてあるんですね
11. タブをスペースに置換
タブ1文字につきスペース1文字に置換せよ.確認にはsedコマンド,trコマンド,もしくはexpandコマンドを用いよ.
# リスト内包表記で各行のタブを1文字スペースに変換
space_text = [line.expandtabs(1) for line in open('./hightemp.txt')]
[print(line) for line in space_text]
# 確認用コマンド
# $ cat ./hightemp.txt | tr '\t' ' '
$ python 11.py
高知県 江川崎 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
$ cat ./hightemp.txt | tr '\t' ' '
高知県 江川崎 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
改行入ってしまっているのが少し気になる
12. 1列目をcol1.txtに,2列目をcol2.txtに保存
各行の1列目だけを抜き出したものをcol1.txtに,2列目だけを抜き出したものをcol2.txtとしてファイルに保存せよ.確認にはcutコマンドを用いよ.
# リスト内包表記で各行をタブでスライスして、1列目と2列目をリスト化
col1 = [line.split('\t')[0] for line in open('./hightemp.txt')]
col2 = [line.split('\t')[1] for line in open('./hightemp.txt')]
# 書き込みモードでファイルオープン
f1 = open('./col1.txt','w')
f2 = open('./col2.txt','w')
# 改行コードでjoin
f1.write('\n'.join(col1))
f2.write('\n'.join(col2))
# 確認用コマンド
# $ cat ./hightemp.txt | cut -f 1
# $ cat ./hightemp.txt | cut -f 2
$ python 12.py ← col1.txt,col2.txtが作られる
$ cat ./hightemp.txt | cut -f 1
高知県
埼玉県
岐阜県
山形県
山梨県
和歌山県
静岡県
山梨県
埼玉県
群馬県
群馬県
愛知県
千葉県
静岡県
愛媛県
山形県
岐阜県
群馬県
千葉県
埼玉県
大阪府
山梨県
山形県
愛知県
$ cat ./hightemp.txt | cut -f 2
江川崎
熊谷
多治見
山形
甲府
かつらぎ
天竜
勝沼
越谷
館林
上里見
愛西
牛久
佐久間
宇和島
酒田
美濃
前橋
茂原
鳩山
豊中
大月
鶴岡
名古屋
高知県
埼玉県
岐阜県
山形県
山梨県
和歌山県
静岡県
山梨県
埼玉県
群馬県
群馬県
愛知県
千葉県
静岡県
愛媛県
山形県
岐阜県
群馬県
千葉県
埼玉県
大阪府
山梨県
山形県
愛知県
江川崎
熊谷
多治見
山形
甲府
かつらぎ
天竜
勝沼
越谷
館林
上里見
愛西
牛久
佐久間
宇和島
酒田
美濃
前橋
茂原
鳩山
豊中
大月
鶴岡
名古屋
13. col1.txtとcol2.txtをマージ
12で作ったcol1.txtとcol2.txtを結合し,元のファイルの1列目と2列目をタブ区切りで並べたテキストファイルを作成せよ.確認にはpasteコマンドを用いよ.
# とりあえず読み込み
col1 = [line for line in open('./col1.txt')]
col2 = [line for line in open('./col2.txt')]
new_file = open('./new_file.txt','w')
# zipで2つのリストを連結して処理
# 2つのリストをタブで連結、改行コードを削除を1行として
# 最後に改行いれて次の行へ
for col in zip(col1, col2):
new_file.write('\t'.join(col).replace('\n',''))
new_file.write('\n')
# 確認用コマンド
# $ paste ./col1.txt ./col2.txt
$ python 13.py
$ cat new_file.txt
高知県 江川崎
埼玉県 熊谷
岐阜県 多治見
山形県 山形
山梨県 甲府
和歌山県 かつらぎ
静岡県 天竜
山梨県 勝沼
埼玉県 越谷
群馬県 館林
群馬県 上里見
愛知県 愛西
千葉県 牛久
静岡県 佐久間
愛媛県 宇和島
山形県 酒田
岐阜県 美濃
群馬県 前橋
千葉県 茂原
埼玉県 鳩山
大阪府 豊中
山梨県 大月
山形県 鶴岡
愛知県 名古屋
$ paste ./col1.txt ./col2.txt
高知県 江川崎
埼玉県 熊谷
岐阜県 多治見
山形県 山形
山梨県 甲府
和歌山県 かつらぎ
静岡県 天竜
山梨県 勝沼
埼玉県 越谷
群馬県 館林
群馬県 上里見
愛知県 愛西
千葉県 牛久
静岡県 佐久間
愛媛県 宇和島
山形県 酒田
岐阜県 美濃
群馬県 前橋
千葉県 茂原
埼玉県 鳩山
大阪府 豊中
山梨県 大月
山形県 鶴岡
愛知県 名古屋
14. 先頭からN行を出力
自然数Nをコマンドライン引数などの手段で受け取り,入力のうち先頭のN行だけを表示せよ.確認にはheadコマンドを用いよ.
# input()で標準入力受け付けれる
# int()でinteger型に変換
input = int(input())
lines = [line for line in open('./hightemp.txt')]
print(''.join(lines[:input]))
# 確認用コマンド
# $ head ./hightemp.txt -n
$ python 14.py
4 ← 標準入力
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
山形県 山形 40.8 1933-07-25
$ head ./hightemp.txt -n 4
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
山形県 山形 40.8 1933-07-25
15. 末尾のN行を出力
自然数Nをコマンドライン引数などの手段で受け取り,入力のうち末尾のN行だけを表示せよ.確認にはtailコマンドを用いよ.
# 14と同じ感じ
input = int(input())
lines = [line for line in open('./hightemp.txt')]
# スライスおさらい
# 負の数与えると末尾からの順番で扱える
print(''.join(lines[-input:]))
# 確認用コマンド
# $ tail ./hightemp.txt -n
$ python 15.py
3 ← 標準入力
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02
$ tail ./hightemp.txt -n 3
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02
16. ファイルをN分割する
自然数Nをコマンドライン引数などの手段で受け取り,入力のファイルを行単位でN分割せよ.同様の処理をsplitコマンドで実現せよ.
input = int(input())
lines = [line for line in open('./hightemp.txt')]
sublist = [''.join(lines[i:i+input]) for i in range(0,len(lines),input)]
# python結果確認用
for i in sublist:
print(i)
# 確認用コマンド
# $ split -l N ./hightemp.txt
$ python 16.py
9 ← 標準入力
高知県 江川崎 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
$ split -l 9 ./hightemp.txt
$ ls
10.py 12.py 14.py 16.py 18.py col1.txt hightemp.txt xaa xac
11.py 13.py 15.py 17.py 19.py col2.txt new_file.txt xab
$ cat xaa
高知県 江川崎 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
17. 1列目の文字列の異なり
1列目の文字列の種類(異なる文字列の集合)を求めよ.確認にはsort, uniqコマンドを用いよ.
# 1列目のデータを取り出し
col1 = [line.split('\t')[0] for line in open('./hightemp.txt')]
output = []
# 別リストに追加していく、重複した値は入れない
for c in col1:
if c not in output:
output.append(c)
print(output)
# $ cat hightemp.txt | cut -f 1 | sort -k1 | uniq
$ python 17.py
['高知県', '埼玉県', '岐阜県', '山形県', '山梨県', '和歌山県', '静岡県', '群馬県', '愛知県', '千葉県', '愛媛県', '大阪府']
$ cat hightemp.txt | cut -f 1 | sort -k1 | uniq
愛知県
愛媛県
岐阜県
群馬県
高知県
埼玉県
山形県
山梨県
静岡県
千葉県
大阪府
和歌山県
18. 各行を3コラム目の数値の降順にソート
各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ).確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい).
# 3列目のリストと、行ごとのリストをとる
values = [line.split('\t')[2] for line in open('./hightemp.txt')]
keys = [line for line in open('./hightemp.txt')]
dic = dict(zip(keys,values))
# 3列目の値でソート
sort_dic = sorted(dic.items(), key=lambda x:x[1])
for k,v in sort_dic:
print(k)
# 確認用コマンド
# $ cat hightemp.txt | sort -k3
$ python 18.py
千葉県 茂原 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
岐阜県 美濃 40 2007-08-16
群馬県 前橋 40 2001-07-24
山形県 酒田 40.1 1978-08-03
千葉県 牛久 40.2 2004-07-20
静岡県 佐久間 40.2 2001-07-24
愛媛県 宇和島 40.2 1927-07-22
群馬県 館林 40.3 2007-08-16
群馬県 上里見 40.3 1998-07-04
愛知県 愛西 40.3 1994-08-05
埼玉県 越谷 40.4 2007-08-16
山梨県 勝沼 40.5 2013-08-10
和歌山県 かつらぎ 40.6 1994-08-08
静岡県 天竜 40.6 1994-08-04
山梨県 甲府 40.7 2013-08-10
山形県 山形 40.8 1933-07-25
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
高知県 江川崎 41 2013-08-12
$ cat hightemp.txt | sort -k3
愛知県 名古屋 39.9 1942-08-02
山形県 鶴岡 39.9 1978-08-03
山梨県 大月 39.9 1990-07-19
大阪府 豊中 39.9 1994-08-08
埼玉県 鳩山 39.9 1997-07-05
千葉県 茂原 39.9 2013-08-11
群馬県 前橋 40 2001-07-24
岐阜県 美濃 40 2007-08-16
山形県 酒田 40.1 1978-08-03
愛媛県 宇和島 40.2 1927-07-22
静岡県 佐久間 40.2 2001-07-24
千葉県 牛久 40.2 2004-07-20
愛知県 愛西 40.3 1994-08-05
群馬県 上里見 40.3 1998-07-04
群馬県 館林 40.3 2007-08-16
埼玉県 越谷 40.4 2007-08-16
山梨県 勝沼 40.5 2013-08-10
静岡県 天竜 40.6 1994-08-04
和歌山県 かつらぎ 40.6 1994-08-08
山梨県 甲府 40.7 2013-08-10
山形県 山形 40.8 1933-07-25
岐阜県 多治見 40.9 2007-08-16
埼玉県 熊谷 40.9 2007-08-16
高知県 江川崎 41 2013-08-12
19. 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる
各行の1列目の文字列の出現頻度を求め,その高い順に並べて表示せよ.確認にはcut, uniq, sortコマンドを用いよ.
from collections import Counter
# 1列目のデータを取り出し
col1 = [line.split('\t')[0] for line in open('./hightemp.txt')]
# collections.Counterを利用
counter = Counter(col1)
for word,count in counter.most_common():
print(word+', '+str(count))
# 確認用コマンド
# $ cat ./hightemp.txt | cut -f 1 | sort | uniq -c | sort -r
$ python 19.py
埼玉県, 3
山形県, 3
山梨県, 3
群馬県, 3
岐阜県, 2
静岡県, 2
愛知県, 2
千葉県, 2
高知県, 1
和歌山県, 1
愛媛県, 1
大阪府, 1
$ cat ./hightemp.txt | cut -f 1 | sort | uniq -c | sort -r
3 山梨県
3 山形県
3 埼玉県
3 群馬県
2 千葉県
2 静岡県
2 岐阜県
2 愛知県
1 和歌山県
1 大阪府
1 高知県
1 愛媛県
2017/03/18修正
コメントいただいたので修正
# リスト内包表記使ってみる
# num_lines = len(list(open('./hightemp.txt')))
# ジェネレータ内包表記
# 1行づつ読み込み、行数カウント
# リスト内包表記のようにリストを作成しないためメモリ使用量が減る
num_lines = sum(1 for line in open('./hightemp.txt'))
print(num_lines)
リスト内包表記ではメモリにファイルデータを一旦すべて載せてしまうし
無駄にリストを作成することになってしまうので
なるべくジェネレータ内包表記を使ったほうがよいらしい
# リスト内包表記で各行のタブを1文字スペースに変換
space_text = [line.expandtabs(1) for line in open('./hightemp.txt')]
# python3からのprint関数では第2引数にend=""で""内の文字を終端文字として扱える
# end=""だと改行なしとなる
print(''.join(space_text),end='')
print関数の第2引数でend=""を使うと
終端文字を設定できる
変な改行してたのを解消
# リスト内包表記で各行をタブでスライスして、1列目と2列目をリスト化
# col1 = [line.split('\t')[0] for line in open('./hightemp.txt')]
# col2 = [line.split('\t')[1] for line in open('./hightemp.txt')]
# ジェネレータ内包表記
col1 = '\n'.join(line.split('\t')[0] for line in open('./hightemp.txt'))
col2 = '\n'.join(line.split('\t')[1] for line in open('./hightemp.txt'))
# 書き込みモードでファイルオープン
f1 = open('./col1.txt','w')
f2 = open('./col2.txt','w')
# 改行コードでjoin
f1.write(col1)
f2.write(col2)
# input()で標準入力受け付けれる
# int()でinteger型に変換
input_num = int(input())
lines = [line for line in open('./hightemp.txt')]
print(''.join(lines[:input_num]))
# 14と同じ感じ
input_num = int(input())
lines = [line for line in open('./hightemp.txt')]
# スライスおさらい
# 負の数与えると末尾からの順番で扱える
print(''.join(lines[-input_num:]))
input_num = int(input())
lines = [line for line in open('./hightemp.txt')]
sublist = [''.join(lines[i:i+input_num]) for i in range(0,len(lines),input_num)]
# python結果確認用
for i in sublist:
print(i)
input = int(input())だとこれ以降input関数使用不可になるため
変数名をinput_numに変更
# 3列目のリストと、行ごとのリストをとる
values = [line.split('\t')[2] for line in open('./hightemp.txt')]
keys = [line for line in open('./hightemp.txt')]
dic = dict(zip(keys,values))
# 3列目の値でソート
sort_dic = sorted(dic.items(), key=lambda x:x[1])
for k,v in sort_dic:
print(k,end='')
print(**,end='')で変な改行を消した
from collections import Counter
# 1列目のデータを取り出し
# col1 = [line.split('\t')[0] for line in open('./hightemp.txt')]
# collections.Counterを利用
# counter = Counter(col1)
# 1行にまとめてジェネレータ内包表記のほうが良い?
counter = Counter(line.split('\t')[0] for line in open('./hightemp.txt'))
for word,count in counter.most_common():
print(word+', '+str(count))
全体的にファイル読み込み後にリストでの処理を行うの以外は
すべてジェネレータ内包表記に修正した