はじめに
自然言語処理を基礎からやり直そうと思い、言語処理100本ノック(http://www.cl.ecei.tohoku.ac.jp/nlp100/ )に取り組み始めました。言語処理100本ノックは、東北大学の乾・岡崎研究室(http://www.cl.ecei.tohoku.ac.jp/ )の岡崎先生が提供されている自然言語処理の練習問題集です。
今回は、その第2章に取り組みました。UNIXコマンドでの検証に関しては省略します。
#動作環境
Ubuntu 16.04 LTS
Python 3.6.2
Jupyter notebook
No.10 行数のカウント
行数をカウントせよ.確認にはwcコマンドを用いよ.
with open('hightemp.txt', 'r', encoding='utf-8') as f :
print(len(f.readlines()))
24
No.11 タブをスペースに置換
タブ1文字につきスペース1文字に置換せよ.確認にはsedコマンド,trコマンド,もしくはexpandコマンドを用いよ.
with open('hightemp.txt', 'r', encoding='utf-8') as f :
print(f.read().replace('\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
No.12 1列目をcol1.txtに,2列目をcol2.txtに保存
各行の1列目だけを抜き出したものをcol1.txtに,2列目だけを抜き出したものをcol2.txtとしてファイルに保存せよ.確認にはcutコマンドを用いよ.
with open('hightemp.txt', 'r', encoding='utf-8') as original, \
open('col1.txt', 'w', encoding='utf-8') as col1, \
open('col2.txt', 'w', encoding='utf-8') as col2:
for row in original.readlines() :
row_split = row.split('\t')
col1.write(row_split[0] + '\n')
col2.write(row_split[1] + '\n')
pandas版
from IPython.display import display
import pandas as pd
input_data = pd.read_csv('hightemp.txt',sep='\t',header=None)
input_data.columns = ['Prefacture', 'City', 'Temperature', 'Date']
input_data['Prefacture'].to_csv('col1.txt', encoding='utf-8',index=False)
input_data['City'].to_csv('col2.txt', encoding='utf-8',index=False)
No.13 col1.txtとcol2.txtをマージ
12で作ったcol1.txtとcol2.txtを結合し,元のファイルの1列目と2列目をタブ区切りで並べたテキストファイルを作成せよ.確認にはpasteコマンドを用いよ.
with open('col1.txt', 'r', encoding='utf-8') as col1, \
open('col2.txt', 'r', encoding='utf-8') as col2, \
open('merged.txt', 'w', encoding='utf-8') as merged:
for row1, row2 in zip(col1.readlines(), col2.readlines()) :
merged.write(row1.rstrip() + '\t' + row2)
pandas版
import pandas as pd
col1 = pd.read_csv('col1.txt', header=None)
col2 = pd.read_csv('col2.txt', header=None)
merged = pd.concat([col1, col2], axis=1)
merged.columns = ['Prefacture', 'City']
merged.to_csv('merged.tsv', sep='\t',header=None ,index=False, encoding='utf-8')
No.14 先頭からN行を出力
自然数Nをコマンドライン引数などの手段で受け取り,入力のうち先頭のN行だけを表示せよ.確認にはheadコマンドを用いよ.
print('自然数をひとつ入力してください。N = ', end='')
input_num = input()
input_num = int(input_num)
with open('hightemp.txt', encoding='utf-8') as input_data :
lines = input_data.readlines()
for line in lines[ : input_num] :
print(line, end='')
自然数をひとつ入力してください。N = 4
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
山形県 山形 40.8 1933-07-25
pandas版
from IPython.display import display
import pandas as pd
print('自然数をひとつ入力してください。N = ', end='')
input_num = input()
input_num = int(input_num)
display(pd.read_csv('hightemp.txt', sep='\t').head(input_num))
自然数をひとつ入力してください。N = 4
高知県 | 江川崎 | 41 | 2013-08-12 | |
---|---|---|---|---|
0 | 埼玉県 | 熊谷 | 40.9 | 2007-08-16 |
1 | 岐阜県 | 多治見 | 40.9 | 2007-08-16 |
2 | 山形県 | 山形 | 40.8 | 1933-07-25 |
3 | 山梨県 | 甲府 | 40.7 | 2013-08-10 |
No.15 末尾のN行を出力
自然数Nをコマンドライン引数などの手段で受け取り,入力のうち末尾のN行だけを表示せよ.確認にはtailコマンドを用いよ.
print('自然数をひとつ入力してください。N = ', end='')
input_num = input()
input_num = int(input_num)
with open('hightemp.txt', encoding='utf-8') as input_data :
lines = input_data.readlines()
for line in lines[-input_num : ] :
print(line, end='')
自然数をひとつ入力してください。N = 4
大阪府 豊中 39.9 1994-08-08
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02
pandas版
from IPython.display import display
import pandas as pd
print('自然数をひとつ入力してください。N = ', end='')
input_num = input()
input_num = int(input_num)
display(pd.read_csv('hightemp.txt', sep='\t').tail(input_num))
自然数をひとつ入力してください。N = 4
高知県 | 江川崎 | 41 | 2013-08-12 | |
---|---|---|---|---|
19 | 大阪府 | 豊中 | 39.9 | 1994-08-08 |
20 | 山梨県 | 大月 | 39.9 | 1990-07-19 |
21 | 山形県 | 鶴岡 | 39.9 | 1978-08-03 |
22 | 愛知県 | 名古屋 | 39.9 | 1942-08-02 |
No.16 ファイルをN分割する
自然数Nをコマンドライン引数などの手段で受け取り,入力のファイルを行単位でN分割せよ.同様の処理をsplitコマンドで実現せよ.
print('自然数をひとつ入力してください。N = ', end='')
input_num = input()
input_num = int(input_num)
with open('hightemp.txt', encoding='utf-8') as input_data :
lines = input_data.readlines()
lines_size = len(lines)
unit_size = lines_size // input_num
res = lines_size % input_num
indeces = [0]
for i in range(1, input_num) :
indeces.append(indeces[-1] + unit_size)
if res > 0 :
indeces[-1] += 1
res -= 1
indeces.append(lines_size)
for i in range(len(indeces) - 1) :
with open('hightemp_split_' + str(i) + '.txt', 'w', encoding='utf-8') as output_data :
output_data.writelines(lines[indeces[i] : indeces[i + 1]])
自然数をひとつ入力してください。N = 7
pandas版
import pandas as pd
print('自然数をひとつ入力してください。N = ', end='')
input_num = input()
input_num = int(input_num)
with open('hightemp.txt', encoding='utf-8') as input_data :
lines = input_data.readlines()
lines_size = len(lines)
unit_size = lines_size // input_num
res = lines_size % input_num
indeces = [0]
for i in range(1, input_num) :
indeces.append(indeces[-1] + unit_size)
if res > 0 :
indeces[-1] += 1
res -= 1
indeces.append(lines_size)
自然数をひとつ入力してください。N = 7
No.17 1列目の文字列の異なり
1列目の文字列の種類(異なる文字列の集合)を求めよ.確認にはsort, uniqコマンドを用いよ.
import pandas as pd
input_data = pd.read_csv('hightemp.txt',sep='\t',header=None)
prefacture = input_data.iloc[:,0]
print('異なる文字列数は、{}'.format(len(prefacture.unique())))
異なる文字列数は、12
No.18 各行を3コラム目の数値の降順にソート
各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ).確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい).
from IPython.display import display
import pandas as pd
input_data = pd.read_csv('hightemp.txt',sep='\t',header=None)
input_data.columns = ['Prefacture', 'City', 'Temperature', 'Date']
output_data = input_data.sort_values(by='Temperature', ascending=False)
output_data.index = range(len(output_data))
display(output_data)
Prefacture | City | Temperature | Date | |
---|---|---|---|---|
0 | 高知県 | 江川崎 | 41.0 | 2013-08-12 |
1 | 岐阜県 | 多治見 | 40.9 | 2007-08-16 |
2 | 埼玉県 | 熊谷 | 40.9 | 2007-08-16 |
3 | 山形県 | 山形 | 40.8 | 1933-07-25 |
4 | 山梨県 | 甲府 | 40.7 | 2013-08-10 |
5 | 和歌山県 | かつらぎ | 40.6 | 1994-08-08 |
6 | 静岡県 | 天竜 | 40.6 | 1994-08-04 |
7 | 山梨県 | 勝沼 | 40.5 | 2013-08-10 |
8 | 埼玉県 | 越谷 | 40.4 | 2007-08-16 |
9 | 群馬県 | 館林 | 40.3 | 2007-08-16 |
10 | 群馬県 | 上里見 | 40.3 | 1998-07-04 |
11 | 愛知県 | 愛西 | 40.3 | 1994-08-05 |
12 | 愛媛県 | 宇和島 | 40.2 | 1927-07-22 |
13 | 千葉県 | 牛久 | 40.2 | 2004-07-20 |
14 | 静岡県 | 佐久間 | 40.2 | 2001-07-24 |
15 | 山形県 | 酒田 | 40.1 | 1978-08-03 |
16 | 岐阜県 | 美濃 | 40.0 | 2007-08-16 |
17 | 群馬県 | 前橋 | 40.0 | 2001-07-24 |
18 | 千葉県 | 茂原 | 39.9 | 2013-08-11 |
19 | 埼玉県 | 鳩山 | 39.9 | 1997-07-05 |
20 | 大阪府 | 豊中 | 39.9 | 1994-08-08 |
21 | 山梨県 | 大月 | 39.9 | 1990-07-19 |
22 | 山形県 | 鶴岡 | 39.9 | 1978-08-03 |
23 | 愛知県 | 名古屋 | 39.9 | 1942-08-02 |
No,19 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる
各行の1列目の文字列の出現頻度を求め,その高い順に並べて表示せよ.確認にはcut, uniq, sortコマンドを用いよ.
from IPython.display import display
import pandas as pd
input_data = pd.read_csv('hightemp.txt',sep='\t',header=None)
input_data.columns = ['Prefacture', 'City', 'Temperature', 'Date']
input_data['Prefacture'].value_counts()
山梨県 3
埼玉県 3
群馬県 3
山形県 3
愛知県 2
静岡県 2
千葉県 2
岐阜県 2
和歌山県 1
高知県 1
愛媛県 1
大阪府 1
Name: Prefacture, dtype: int64
#おわりに
後半の問題は、pandasを使った方が便利だという印象でした。
間違いを見つけられた方は、ご指摘いただけると幸いです。