言語処理100本ノック　第2章 UNIXコマンドの基礎


## はじめに
自然言語処理を基礎からやり直そうと思い、言語処理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コマンドを用いよ．


```python
with open('hightemp.txt', 'r', encoding='utf-8') as f :
    print(len(f.readlines()))
```

    24


# No.11 タブをスペースに置換
タブ1文字につきスペース1文字に置換せよ．確認にはsedコマンド，trコマンド，もしくはexpandコマンドを用いよ．


```python
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コマンドを用いよ．


```python
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版


```python
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コマンドを用いよ．


```python
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版


```python
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コマンドを用いよ．


```python
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版


```python
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



<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>高知県</th>
      <th>江川崎</th>
      <th>41</th>
      <th>2013-08-12</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>埼玉県</td>
      <td>熊谷</td>
      <td>40.9</td>
      <td>2007-08-16</td>
    </tr>
    <tr>
      <th>1</th>
      <td>岐阜県</td>
      <td>多治見</td>
      <td>40.9</td>
      <td>2007-08-16</td>
    </tr>
    <tr>
      <th>2</th>
      <td>山形県</td>
      <td>山形</td>
      <td>40.8</td>
      <td>1933-07-25</td>
    </tr>
    <tr>
      <th>3</th>
      <td>山梨県</td>
      <td>甲府</td>
      <td>40.7</td>
      <td>2013-08-10</td>
    </tr>
  </tbody>
</table>
</div>


# No.15 末尾のN行を出力
自然数Nをコマンドライン引数などの手段で受け取り，入力のうち末尾のN行だけを表示せよ．確認にはtailコマンドを用いよ．


```python
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版


```python
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



<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
</style>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>高知県</th>
      <th>江川崎</th>
      <th>41</th>
      <th>2013-08-12</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>19</th>
      <td>大阪府</td>
      <td>豊中</td>
      <td>39.9</td>
      <td>1994-08-08</td>
    </tr>
    <tr>
      <th>20</th>
      <td>山梨県</td>
      <td>大月</td>
      <td>39.9</td>
      <td>1990-07-19</td>
    </tr>
    <tr>
      <th>21</th>
      <td>山形県</td>
      <td>鶴岡</td>
      <td>39.9</td>
      <td>1978-08-03</td>
    </tr>
    <tr>
      <th>22</th>
      <td>愛知県</td>
      <td>名古屋</td>
      <td>39.9</td>
      <td>1942-08-02</td>
    </tr>
  </tbody>
</table>
</div>


# No.16 ファイルをN分割する
自然数Nをコマンドライン引数などの手段で受け取り，入力のファイルを行単位でN分割せよ．同様の処理をsplitコマンドで実現せよ．


```python
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版


```python
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列目の文字列の種類（異なる文字列の集合）を求めよ．確認にはsort, uniqコマンドを用いよ．


```python
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コマンドを用いよ（この問題はコマンドで実行した時の結果と合わなくてもよい）．


```python
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)
```


<div>
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>Prefacture</th>
      <th>City</th>
      <th>Temperature</th>
      <th>Date</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>高知県</td>
      <td>江川崎</td>
      <td>41.0</td>
      <td>2013-08-12</td>
    </tr>
    <tr>
      <th>1</th>
      <td>岐阜県</td>
      <td>多治見</td>
      <td>40.9</td>
      <td>2007-08-16</td>
    </tr>
    <tr>
      <th>2</th>
      <td>埼玉県</td>
      <td>熊谷</td>
      <td>40.9</td>
      <td>2007-08-16</td>
    </tr>
    <tr>
      <th>3</th>
      <td>山形県</td>
      <td>山形</td>
      <td>40.8</td>
      <td>1933-07-25</td>
    </tr>
    <tr>
      <th>4</th>
      <td>山梨県</td>
      <td>甲府</td>
      <td>40.7</td>
      <td>2013-08-10</td>
    </tr>
    <tr>
      <th>5</th>
      <td>和歌山県</td>
      <td>かつらぎ</td>
      <td>40.6</td>
      <td>1994-08-08</td>
    </tr>
    <tr>
      <th>6</th>
      <td>静岡県</td>
      <td>天竜</td>
      <td>40.6</td>
      <td>1994-08-04</td>
    </tr>
    <tr>
      <th>7</th>
      <td>山梨県</td>
      <td>勝沼</td>
      <td>40.5</td>
      <td>2013-08-10</td>
    </tr>
    <tr>
      <th>8</th>
      <td>埼玉県</td>
      <td>越谷</td>
      <td>40.4</td>
      <td>2007-08-16</td>
    </tr>
    <tr>
      <th>9</th>
      <td>群馬県</td>
      <td>館林</td>
      <td>40.3</td>
      <td>2007-08-16</td>
    </tr>
    <tr>
      <th>10</th>
      <td>群馬県</td>
      <td>上里見</td>
      <td>40.3</td>
      <td>1998-07-04</td>
    </tr>
    <tr>
      <th>11</th>
      <td>愛知県</td>
      <td>愛西</td>
      <td>40.3</td>
      <td>1994-08-05</td>
    </tr>
    <tr>
      <th>12</th>
      <td>愛媛県</td>
      <td>宇和島</td>
      <td>40.2</td>
      <td>1927-07-22</td>
    </tr>
    <tr>
      <th>13</th>
      <td>千葉県</td>
      <td>牛久</td>
      <td>40.2</td>
      <td>2004-07-20</td>
    </tr>
    <tr>
      <th>14</th>
      <td>静岡県</td>
      <td>佐久間</td>
      <td>40.2</td>
      <td>2001-07-24</td>
    </tr>
    <tr>
      <th>15</th>
      <td>山形県</td>
      <td>酒田</td>
      <td>40.1</td>
      <td>1978-08-03</td>
    </tr>
    <tr>
      <th>16</th>
      <td>岐阜県</td>
      <td>美濃</td>
      <td>40.0</td>
      <td>2007-08-16</td>
    </tr>
    <tr>
      <th>17</th>
      <td>群馬県</td>
      <td>前橋</td>
      <td>40.0</td>
      <td>2001-07-24</td>
    </tr>
    <tr>
      <th>18</th>
      <td>千葉県</td>
      <td>茂原</td>
      <td>39.9</td>
      <td>2013-08-11</td>
    </tr>
    <tr>
      <th>19</th>
      <td>埼玉県</td>
      <td>鳩山</td>
      <td>39.9</td>
      <td>1997-07-05</td>
    </tr>
    <tr>
      <th>20</th>
      <td>大阪府</td>
      <td>豊中</td>
      <td>39.9</td>
      <td>1994-08-08</td>
    </tr>
    <tr>
      <th>21</th>
      <td>山梨県</td>
      <td>大月</td>
      <td>39.9</td>
      <td>1990-07-19</td>
    </tr>
    <tr>
      <th>22</th>
      <td>山形県</td>
      <td>鶴岡</td>
      <td>39.9</td>
      <td>1978-08-03</td>
    </tr>
    <tr>
      <th>23</th>
      <td>愛知県</td>
      <td>名古屋</td>
      <td>39.9</td>
      <td>1942-08-02</td>
    </tr>
  </tbody>
</table>
</div>


# No,19 各行の1コラム目の文字列の出現頻度を求め，出現頻度の高い順に並べる
各行の1列目の文字列の出現頻度を求め，その高い順に並べて表示せよ．確認にはcut, uniq, sortコマンドを用いよ．


```python
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を使った方が便利だという印象でした。
間違いを見つけられた方は、ご指摘いただけると幸いです。