Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 3 years have passed since last update.

言語処理100本ノック2020(Rev1)をやってみました。

Posted at

第2章: UNIXコマンド

この章では、以下のデータを使用します。

popular-names.txt
アメリカで生まれた赤ちゃんの「名前」「性別」「人数」「年」をタブ区切り形式で格納したファイル.

またここでは、Google Colaboratoryを使用しています。

10. 行数のカウント

行数をカウントせよ.確認にはwcコマンドを用いよ.

requestsを用いた解

import requests

url = "https://nlp100.github.io/data/popular-names.txt"
try:
  r = requests.get(url)
  print(sum([1 for _ in r.iter_lines()]))
except requests.exceptions.RequestException as err:
    print(err)

<出力>

2780

Pandasを使用した解

import numpy as np
import pandas as pd

datas = pd.read_csv("https://nlp100.github.io/data/popular-names.txt",sep='\t',header=None)
datas.head()
print(datas.shape[0])

<出力>

2780

wcコマンドによる解

!wget "https://nlp100.github.io/data/popular-names.txt"
%cat "popular-names.txt" | wc -l

<出力>

--2020-08-10 05:08:12--  https://nlp100.github.io/data/popular-names.txt
Resolving nlp100.github.io (nlp100.github.io)... 185.199.108.153, 185.199.109.153, 185.199.110.153, ...
Connecting to nlp100.github.io (nlp100.github.io)|185.199.108.153|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 55026 (54K) [text/plain]
Saving to: ‘popular-names.txt’

popular-names.txt 100%[===================>]  53.74K  --.-KB/s    in 0.03s   

2020-08-10 05:08:12 (2.03 MB/s) - ‘popular-names.txt’ saved [55026/55026]

2780

11. タブをスペースに置換

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

直接ダウンロードストリームを変換して表示

import requests

url = "https://nlp100.github.io/data/popular-names.txt"
try:
  r = requests.get(url)
  print(r.text.replace("\t"," "))
except requests.exceptions.RequestException as err:
    print(err)

<出力>

Mary F 7065 1880
Anna F 2604 1880
Emma F 2003 1880
・・・

ダウンロードしたファイルを変換して表示

with open("popular-names.txt", 'r') as f:
    lines = f.read() # readlines()で読むと改行コードが付加されるため、ここではread()を使用。

print(lines.replace("\t", " "))

<出力>

Mary F 7065 1880
Anna F 2604 1880
Emma F 2003 1880
・・・

sedを使用

!sed "s/\t/ /g" "popular-names.txt" | head -n 3

<出力>

Mary F 7065 1880
Anna F 2604 1880
Emma F 2003 1880

12. 1列目をcol1.txtに,2列目をcol2.txtに保存

各行の1列目だけを抜き出したものをcol1.txtに,2列目だけを抜き出したものをcol2.txtとしてファイルに保存せよ.確認にはcutコマンドを用いよ.

import numpy as np
import pandas as pd

datas = pd.read_csv("https://nlp100.github.io/data/popular-names.txt",sep='\t',header=None)
datas.columns=['Name','Sex','Count','Year']

datas.to_csv(path_or_buf="col1.txt",sep=" ",columns=["Name"],header=False,index=False,)
datas.to_csv(path_or_buf="col2.txt",sep=" ",columns=["Sex"],header=False,index=False,)

<確認1>

%cat col1.txt | head -n 5

<出力>

Mary
Anna
Emma
Elizabeth
Minnie

<確認2>

%cat col2.txt | head -n 5

<出力>

F
F
F
F
F

sedでの確認

!cut -f 1 "popular-names.txt" | head -n 3
!cut -f 2 "popular-names.txt" | head -n 3

<出力>

Mary
Anna
Emma
F
F
F

13. col1.txtとcol2.txtをマージ

12で作ったcol1.txtとcol2.txtを結合し,元のファイルの1列目と2列目をタブ区切りで並べたテキストファイルを作成せよ.確認にはpasteコマンドを用いよ.

import pandas as pd

data1 = pd.read_csv('col1.txt',header=None)
data2 = pd.read_csv('col2.txt',header=None)

data1['Sex'] = data2[0]
data1.to_csv('2col_data.txt',sep="\t", header=False, index=False)

<確認>

%cat '2col_data.txt' | head -n 3
Mary	F
Anna	F
Emma	F

pasteコマンドによる確認

!paste -d "\t" 'col1.txt' 'col2.txt' | head -n 3

<出力>

Mary	F
Anna	F
Emma	F

14. 先頭からN行を出力

自然数Nをコマンドライン引数などの手段で受け取り,入力のうち先頭のN行だけを表示せよ.確認にはheadコマンドを用いよ.

pythonで実装

def headEx(n, strPath):
  with open(strPath) as f:
    data = f.readlines()
    f.close()
  ret=""
  for i,line in enumerate(data):
    if i> (n-1):
      break
    else:
      ret += line
  return ret

print(headEx(4,'2col_data.txt'))

<出力>

Mary	F
Anna	F
Emma	F
Elizabeth	F

headコマンドで確認

%cat '2col_data.txt' | head -n 4

<出力>

Mary	F
Anna	F
Emma	F
Elizabeth	F

15. 末尾のN行を出力

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

pythonで実装

def tailEx(n, strPath):
  with open(strPath) as f:
    data = f.readlines()

  ret=""
  if len(data) < n:
    n=len(data)
  for line in data[-n-1:-1]:
      ret += line
  return ret

print(tailEx(4,'2col_data.txt'))

<出力>

Benjamin	M
Elijah	M
Lucas	M
Mason	M

tailコマンドで確認

%cat '2col_data.txt' | tail -n 4

<出力>

Elijah	M
Lucas	M
Mason	M
Logan	M

16. ファイルをN分割する

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

pythonで実装

def splitN(N, strPath):
    with open(strPath) as f:
        data = f.readlines()

    print(len(data))
    if N<1 or len(data)<N:
        return data
    rowNum = int(len(data) / N)
    print("rowNum = " + str(rowNum))
    
    for cnt in range(N):
        ed = (cnt+1)*rowNum
        if cnt==(N-1):
            ed = len(data)
        ret=""
        for line in data[cnt*rowNum:ed]:
            ret += line
            outPath = strPath.replace('.txt', '__' + str(cnt)+'.txt')
            with open(outPath, 'w') as f:
                f.write(ret)

  
splitN(3,'2col_data.txt')

<出力>

2780
rowNum = 926
%ls
2col_data__0.txt  2col_data__2.txt  col1.txt  popular-names.txt
2col_data__1.txt  2col_data.txt     col2.txt  sample_data/
%cat "2col_data__0.txt" | wc -l
%cat "2col_data__1.txt" | wc -l
%cat "2col_data__2.txt" | wc -l
926
926
928

splitコマンドで確認

!split --number=3 "2col_data.txt" # 3つに分割
%ls

作成されたファイルは自動命名され、xaa,xab,xacという名前で保存されている。

2col_data__0.txt  2col_data__2.txt  col1.txt  popular-names.txt  xaa  xac
2col_data__1.txt  2col_data.txt     col2.txt  sample_data/       xab

分割されたファイルの行数を確認

%cat "xaa" | wc -l
%cat "xab" | wc -l
%cat "xac" | wc -l
947
940
893

行数が異なっている。

%ls -la x*
-rw-r--r-- 1 root root 8359 Aug 12 06:13 xaa
-rw-r--r-- 1 root root 8359 Aug 12 06:13 xab
-rw-r--r-- 1 root root 8360 Aug 12 06:13 xac

splitで単純に個数指定で分割すると、データサイズで等分されるようである。

17. 1列目の文字列の異なり

1列目の文字列の種類(異なる文字列の集合)を求めよ.確認にはcut, sort, uniqコマンドを用いよ.

pythonで実装

import pandas as pd

datas = pd.read_csv("https://nlp100.github.io/data/popular-names.txt",sep='\t',header=None)
print(list(set(datas[0]))[0:3])
print(len(set(datas[0])))

<出力>

['Nancy', 'Rebecca', 'Ethan']
136

uniqコマンドで確認

!cut -f 1 "popular-names.txt" | sort | uniq | wc -l
136

cutコマンドで1列目を取り出し、ソートしてからuniqで重複を除去し、wcで行数をカウントしている。
uniqでは、連続した重複しか重複とみなされないため、sortしてから重複除去を行っている。

18. 各行を3コラム目の数値の降順にソート

各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ).確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい).

pythonで実装

# 17からのつづき
datas = datas.sort_values(by=2, ascending=False)
datas.head(5)

<出力>

0	1	2	3
1340	Linda	F	99689	1947
1360	Linda	F	96211	1948
1350	James	M	94757	1947
1550	Michael	M	92704	1957
1351	Robert	M	91640	1947

sortコマンドで確認

sortコマンドのオプション
-k3 3列目
-n 数値として比較
-r 逆順にソート
-t 区切り文字指定(タブ指定は-t$'\t')

!cat "popular-names.txt" | sort -k3rn -t$'\t' | head -n 5

<出力>

Linda	F	99689	1947
Linda	F	96211	1948
James	M	94757	1947
Michael	M	92704	1957
Robert	M	91640	1947

19. 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる

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

pythonによる実装

import pandas as pd

datas = pd.read_csv("https://nlp100.github.io/data/popular-names.txt",sep='\t',header=None)
print(datas[0].value_counts())

<出力>

James      118
William    111
John       108
Robert     108
Mary        92
          ... 
Laura        1
Rachel       1
Lori         1
Crystal      1
Scott        1
Name: 0, Length: 136, dtype: int64

sortコマンドでの確認

!cut -f 1 "popular-names.txt" | sort | uniq -c | sort -k1rn | head -n 5

<出力>

    118 James
    111 William
    108 John
    108 Robert
     92 Mary
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?