Port 53

明日のための技術メモ

言語処理100本ノック 2020 第2章 後半

nlp100.github.io

第2章 UNIXコマンドの後半(15-19まで)解説書きます。
いい感じにpandas慣れてきて楽しくなってきた。

第2章 前半はこちら

目次

この章で使うファイル

タブ区切りでアメリカの赤ちゃんの名前、性別、人数、生まれた年が記録された
テキストファイル。

 $ head popular-names.txt 
Mary    F   7065    1880
Anna    F   2604    1880
Emma    F   2003    1880
Elizabeth   F   1939    1880
Minnie  F   1746    1880
Margaret    F   1578    1880
Ida F   1472    1880
Alice   F   1414    1880
Bertha  F   1320    1880
Sarah   F   1288    1880

15. 末尾のN行を出力

f:id:saturn-glave:20200502233456p:plain

ほとんど14と一緒。先頭か末尾かの違いだけ。

ポイント

  • pandas.DataFrameから末尾のn行を取り出す時、スライスdf[-n:]df.tail(n) を使う

解答コマンド

最初の3行だけほしい時の場合。
tailコマンドは-n オプションで表示したい行数を指定できる。
デフォルトは先頭10行が表示される。

tail -n 3 popular-names.txt

解答スクリプト

引数はstr型で返ってくるので、intにキャストする。(ポカミスするので2度言いました)

# coding:utf-8
import argparse
import pandas as pd


def arg():
    parser = argparse.ArgumentParser(description='自然数')
    parser.add_argument('n', help='num')
    args = parser.parse_args()
    return(args.n)


def main():
    path = './popular-names.txt'
    n = int(arg())
    df = pd.read_csv(path, sep='\t', header=None)
    print(df[-n:])
    # print(df.tail(n))


if __name__ == "__main__":
    main()

参考記事

note.nkmk.me

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

f:id:saturn-glave:20200502234138p:plain

問題文色々調べた結果、numpyを召喚した。
numpyもそこまで慣れてないので、kaggleにあった100本ノックをやりたい。

ポイント

  • pandas.DataFrameをn分割する際、numpy.split(df, n)を使う

解答コマンド

なんかこれっぽい解答を思いつかなかった。
splitコマンドの-lオプションで、分割する行数を指定できる。
分割後のファイル名は、指定がなければ、xaa, xab, xac...というように命名される。
今回は1000行ずつ分割した。

split -l 1000 popular-names.txt

解答スクリプト

# coding:utf-8
import argparse
import pandas as pd
import numpy as np


def arg():
    parser = argparse.ArgumentParser(description="自然数")
    parser.add_argument('n', help='num')

    args = parser.parse_args()
    return args.n


def main():
    path = './popular-names.txt'
    n = int(arg())
    df = pd.read_csv(path, sep='\t', header=None)

    chunks = np.split(df, n)

    for i in range(n):
        print(chunks[i])


if __name__ == "__main__":
    main()

参考記事

ksomemo.github.io

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

f:id:saturn-glave:20200502234153p:plain

よくありそうな重複削除系問題。

ポイント

  • pandas.DataFrameでもsetが使える

解答コマンド

昇順にソートしてからuniqコマンドで重複削除をする。鉄則。

 cut -f 1 popular-names.txt | sort | uniq

解答スクリプト

# coding:utf-8

import pandas as pd

path = './popular-names.txt'
df = pd.read_csv(path, sep='\t', header=None)
df.columns = ['Name', 'Sex', 'Count', 'Year']

letter = set(df['Name'])
print(letter)

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

f:id:saturn-glave:20200502234206p:plain

これもよくありそうな処理。pandas使いになるには避けて通れない。

ポイント

  • pandas.DataFrameをソートする時、df.sort_values('基準のカラム名') を使う
  • 降順ソートの場合、df.sort_values('基準のカラム名', ascending=False)になる
  • ソート後にdf.reset_index( )インデックスの振り直しが可能。
    • drop=True をつけると、振り直し前のインデックスを削除できる
    • inplace=True をつけると、新しいオブジェクトが生成される

解答コマンド

sortコマンドの-rオプションで降順、-nで数値として並べ替え指定、
-kでソートするキーのフィールド指定、-tでデリミタの指定をする。

ただし、-k 2とすると、「2項目目以降で並べ替え」になってしまうため、
項目1つだけ指定して並べ替えたい時は、-k 2,2のように指定してあげる必要がある。

 sort -r -n -k 4,4  -t '\t'  popular-names.txt

eng-entrance.com

解答スクリプト

# coding:utf-8

import pandas as pd

path = './popular-names.txt'

df = pd.read_csv(path, sep='\t', header=None)
df.columns = ['Name', 'Sex', 'Count', 'Year']

df_s = df.sort_values('Year', ascending=False)
df_s.reset_index(inplace=True, drop=True)
print(df_s)

参考記事

note.nkmk.me

note.nkmk.me

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

f:id:saturn-glave:20200502234217p:plain

集計系の問題。これも覚えたら超便利。

ポイント

  • pandas.DataFrameで集計する時、df['集計対象のカラム名'].value_counts() を使う

解答コマンド

uniqコマンドの-cオプションで集計ができる

 cut -f 1 popular-names.txt | sort | uniq -c | sort -r

解答スクリプト

# coding:utf-8

import pandas as pd

path = './popular-names.txt'
df = pd.read_csv(path, sep='\t', header=None)
df.columns = ['Name', 'Sex', 'Count', 'Year']

print(df['Name'].value_counts())

参考

qiita.com