u++の備忘録

言語処理100本ノック 2020「33. 「AのB」」

問題文

nlp100.github.io

問題の概要

30. 形態素解析結果の読み込み」で作成したデータ構造から、データを取り出します。抽出条件は「名詞」+「の」+「名詞」です。

def parse_mecab(block):
    res = []
    for line in block.split('\n'):
        if line == '':
            return res
        (surface, attr) = line.split('\t')
        attr = attr.split(',')
        lineDict = {
            'surface': surface,
            'base': attr[6],
            'pos': attr[0],
            'pos1': attr[1]
        }
        res.append(lineDict)


def extract_a_no_b(block):
    res = []
    for i in range(1, len(block) - 1):
        if block[i - 1]['pos'] == '名詞' and block[i]['base'] == 'の' and block[i + 1]['pos'] == '名詞':
            res.append(block[i - 1]['surface'] + block[i]['surface'] + block[i + 1]['surface'])
    return res


filename = 'ch04/neko.txt.mecab'
with open(filename, mode='rt', encoding='utf-8') as f:
    blocks = f.read().split('EOS\n')
blocks = list(filter(lambda x: x != '', blocks))
blocks = [parse_mecab(block) for block in blocks]
ans = [extract_a_no_b(block) for block in blocks]
print(ans)

言語処理100本ノック 2020「32. 動詞の原形」

問題文

nlp100.github.io

問題の概要

30. 形態素解析結果の読み込み」で作成したデータ構造から「x['pos'] == '動詞'」の「base」部分を取り出します。

def parse_mecab(block):
    res = []
    for line in block.split('\n'):
        if line == '':
            return res
        (surface, attr) = line.split('\t')
        attr = attr.split(',')
        lineDict = {
            'surface': surface,
            'base': attr[6],
            'pos': attr[0],
            'pos1': attr[1]
        }
        res.append(lineDict)


def extract_base(block):
    res = list(filter(lambda x: x['pos'] == '動詞', block))
    res = [r['base'] for r in res]
    return res


filename = 'ch04/neko.txt.mecab'
with open(filename, mode='rt', encoding='utf-8') as f:
    blocks = f.read().split('EOS\n')
blocks = list(filter(lambda x: x != '', blocks))
blocks = [parse_mecab(block) for block in blocks]
ans = [extract_base(block) for block in blocks]
print(ans[5])

言語処理100本ノック 2020「31. 動詞」

問題文

nlp100.github.io

問題の概要

30. 形態素解析結果の読み込み」で作成したデータ構造から「x['pos'] == '動詞'」の「surface」部分を取り出します。

def parse_mecab(block):
    res = []
    for line in block.split('\n'):
        if line == '':
            return res
        (surface, attr) = line.split('\t')
        attr = attr.split(',')
        lineDict = {
            'surface': surface,
            'base': attr[6],
            'pos': attr[0],
            'pos1': attr[1]
        }
        res.append(lineDict)


def extract_surface(block):
    res = list(filter(lambda x: x['pos'] == '動詞', block))
    res = [r['surface'] for r in res]
    return res


filename = 'ch04/neko.txt.mecab'
with open(filename, mode='rt', encoding='utf-8') as f:
    blocks = f.read().split('EOS\n')
blocks = list(filter(lambda x: x != '', blocks))
blocks = [parse_mecab(block) for block in blocks]
ans = [extract_surface(block) for block in blocks]
print(ans[5])

言語処理100本ノック 2020「30. 形態素解析結果の読み込み」

問題文

nlp100.github.io

問題の概要

本章では、MeCabを用いて形態素解析した結果を読み込んでいきます。手始めに、以下コマンドでファイルに対して形態素解析を実行しましょう。

mecab < ch04/neko.txt > ch04/neko.txt.mecab

あとは、読み込むファイルの形式に応じてデータを取得します。次の4段階で処理しました。

  1. ファイル全体を読み込む
  2. 「split('EOS\n')」で、データを分割する
  3. 不要な行を「filter」で取り除く
  4. 「parse_mecab」関数を適用する
def parse_mecab(block):
    res = []
    for line in block.split('\n'):
        if line == '':
            return res
        (surface, attr) = line.split('\t')
        attr = attr.split(',')
        lineDict = {
            'surface': surface,
            'base': attr[6],
            'pos': attr[0],
            'pos1': attr[1]
        }
        res.append(lineDict)


filename = 'ch04/neko.txt.mecab'
with open(filename, mode='rt', encoding='utf-8') as f:
    blocks = f.read().split('EOS\n')
blocks = list(filter(lambda x: x != '', blocks))
blocks = [parse_mecab(block) for block in blocks]
print(blocks[5])

令和大相撲の暫定王者は誰だ?USWC(非公式相撲世界王者)とともに振り返る

次の記事に影響を受けて、大相撲版をやってみようと思い立ちました。

note.com

概要は次の通りです。

  1. 平成最後の「平成31年春場所」で優勝した白鵬を、令和開始時の「王者」とする
  2. 令和になってからの取り組みで「王者」に勝利した力士を次の「王者」とする
  3. 上の過程を繰り返し、現時点での暫定王者を決める

先人に倣って、あえて名前を付けると「Unofficial Sumo World Championships (USWC)」になるかもしれません。

令和元年夏場所

白鵬(全休)

平成最後の場所で全勝優勝を果たした横綱白鵬ですが、千秋楽の横綱鶴竜戦で右上腕を痛めた影響が長引き、令和元年夏場所は全休に。いきなり、王者の座をかけた取り組み自体が存在しない状況でした。

令和元年名古屋場所

白鵬(1〜8日目)→逸ノ城(9日目)→鶴竜(10〜12日)→友風(13〜14日)→照強(15日目)

休場明けの白鵬は、順調に8連勝し中日で勝ち越し。しかし9日目、平成最後の場所で優勝を争った逸ノ城が寄り切りで白鵬を下します。令和初めての王者交代です。

その逸ノ城ですが、翌日すぐに鶴竜に敗れます。鶴竜は14勝1敗で、7場所ぶり6度目の優勝を飾った好調な場所でした。鶴竜に唯一の土をつけたのは、13日に対戦した友風。友風はこの場所殊勲賞を受賞しましたが、千秋楽に敢闘賞の照強に負けて王者を献上しました。

令和元年秋場所

照強(1日目)→隠岐の海(2〜8日目)→竜電(9〜11日目)→豪栄道(12〜13日目)→御嶽海(14〜15日目)

先場所好調だった照強ですが、番付が上がった影響もあり、この場所は4勝にとどまります。2日目に、隠岐の海に敗れました。隠岐の海は、この場所の序盤絶好調。中日まで全勝で単独トップに立ちました。

隠岐の海の連勝を9日目に止めたのは竜電。この場所は途中で白鵬鶴竜の両横綱が休場する波乱の場所でした。12日目に豪栄道が竜電に勝利、その豪栄道も14日目に御嶽海に敗れます。御嶽海は12勝3敗で15日目を終え、3敗で並んだ貴景勝との決定戦を制して、2度目の優勝を果たしました。

令和元年九州場所

御嶽海(1日目)→北勝富士(2〜4日目)→朝乃山(5日目)→遠藤(6〜8日目)→隠岐の海(9〜11日目)→妙義龍(12日目)→大栄翔(13〜14日目)→炎鵬(15日目)

先々場所・先場所で合計21勝を挙げ、大関取りの期待の中で臨んだ御嶽海。しかし2日目に北勝富士に敗れるなど、序盤から崩れてしまいました。

優勝争いは、14勝を挙げた白鵬が独走。14日目に千秋楽を待たず、令和初、自身が日本国籍を取得してから初となる優勝を決めました。

王者の座は、優勝争いとはあまり絡まずに次々と遷移。5日目に朝乃山、6日目に遠藤、9日目に隠岐の海、12日目に妙義龍、13日目に大栄翔、15日目には炎鵬へと移り変わりました。

令和2年初場所

炎鵬(1日目)→正代(2〜6日目)→豪栄道(7日目)→阿炎(8〜9日目)→高安(10日目)→豪栄道(11日目)→朝乃山(12〜15日目)

幕尻の徳勝龍が14勝1敗で初優勝を飾ったこの場所。前頭5枚目だった炎鵬が持っていた王者の座は、付近の番付の力士の間を移動しました。この場所前に関脇に陥落した高安を11日目に下したのは、大関豪栄道。この場所は5勝10敗と振るいませんでしたが、7日目に続き1場所で2度目の王者に輝きました。

令和2年春場所

朝乃山(1〜5日目)→御嶽海(6日目)→白鵬(7〜9日目)→阿武咲(10日目)→遠藤(11日目)→鶴竜(12〜14日目)→白鵬(15日目)

執筆時点で最新のこの場所は、新型コロナウイルス感染防止のため無観客で開催されました。

先場所の終盤に4連勝で王者を守った朝乃山は序盤から好調で5連勝。しかし6日目、同じく全勝だった御嶽海に黒星をつけられます。その御嶽海も翌日に全勝同士の一番に敗れ、王者の座は白鵬の手に。意外にも白鵬にとって、これがようやく2度目の王者です。

白鵬は10日目に阿武咲に敗れ、その後に遠藤を経て12日目以降は鶴竜が王座に。そして千秋楽は、12勝2敗の白鵬鶴竜横綱同士の結びの一番で、優勝が決まる状況となりました。

この一番を制したのは白鵬鶴竜から王者の座を奪い取り、現時点での「USWC」に君臨しました。横綱同士の優勝をかけた一番が同じく「USWC」を争う場面でもあり、「USWC」のやり方はさほどズレたものでは無いのかもしれません。

統計

白鵬が全休だった場所を除いて、対象範囲は75日間。現在の白鵬が第28代「USWC」で、これまで在籍経験がある力士は19人でした。

最長在籍記録は、朝乃山の9日間です。

f:id:upura:20200420061648p:plain

在籍日数の合計を見ると、白鵬が12日でトップです。

f:id:upura:20200420060417p:plain

在籍した回数では、豪栄道白鵬が3度で並びました。

f:id:upura:20200420060629p:plain

おわりに

本記事では、令和大相撲の「USWC」の推移とともに、各場所を振り返りました。

新型コロナウイルスの影響で夏場所の開催はかなり怪しい状況ですが、今後の動向にも注目していきたいです。余裕があれば、平成から始めた場合の世界線も確認してみたいですね。

「Sports Analyst Meetup #7」を初のオンラインで開催しました #spoana

「Sports Analyst Meetup #7」を、4月16日に開催しました。昨今の情勢を受け、7回目にして初めてのオンライン開催となりました。250名以上の申し込みがあり、だいたい170人程度にご参加いただきました。

spoana.connpass.com

発表内容

今回は4名の方にLTをしていただきました。

f:id:upura:20200417154434p:plain

発表者の方が公開してくださった資料は、connpassページに登録しています。

spoana.connpass.com

アーカイブ

オンライン開催の利点を活かして、発表者の許諾が得られた内容については、YouTubeアーカイブを掲載していく予定です。

youtu.be

togetter

twitterの「#spoana」タグも、盛り上がりを見せていました。

togetter.com

おわりに

初のオンラインで試行錯誤の中の開催でしたが、多くの方にご参加いただき、誠にありがとうございました。今回も素敵な発表をしてくださった方々に、お礼申し上げます。

新型コロナウイルスの流行を受けて、日々のスポーツに関する話題がどうしても少なくなっている印象があります。私も、年会費を払ってはいますが「DAZN」を開く機会が少なくなってしまいました。spoanaを通じて、少しでもスポーツ界の盛り上がりに貢献できればと思っています。

f:id:upura:20200417154124p:plain

言語処理100本ノック 2020「29. 国旗画像のURLを取得する」

問題文

nlp100.github.io

問題の概要

28. MediaWikiマークアップの除去」を改変します。国旗画像のURLを取得を除去する関数「get_url()」を定義し適用します。

import re
import requests
import pandas as pd


def remove_stress(dc):
    r = re.compile("'+")
    return {k: r.sub('', v) for k, v in dc.items()}


def remove_inner_links(dc):
    r = re.compile('\[\[(.+\||)(.+?)\]\]')
    return {k: r.sub(r'\2', v) for k, v in dc.items()}


def remove_mk(v):
    r1 = re.compile("'+")
    r2 = re.compile('\[\[(.+\||)(.+?)\]\]')
    r3 = re.compile('\{\{(.+\||)(.+?)\}\}')
    r4 = re.compile('<\s*?/*?\s*?br\s*?/*?\s*>')
    v = r1.sub('', v)
    v = r2.sub(r'\2', v)
    v = r3.sub(r'\2', v)
    v = r4.sub('', v)
    return v


def get_url(dc):
    url_file = dc['国旗画像'].replace(' ', '_')
    url = 'https://commons.wikimedia.org/w/api.php?action=query&titles=File:' + url_file + '&prop=imageinfo&iiprop=url&format=json'
    data = requests.get(url)
    return re.search(r'"url":"(.+?)"', data.text).group(1)


df = pd.read_json('ch03/jawiki-country.json.gz', lines=True)
uk_text = df.query('title=="イギリス"')['text'].values[0]
uk_texts = uk_text.split('\n')

pattern = re.compile('\|(.+?)\s=\s*(.+)')
ans = {}
for line in uk_texts:
    r = re.search(pattern, line)
    if r:
        ans[r[1]] = r[2]

r = re.compile('\[\[(.+\||)(.+?)\]\]')
ans = {k: r.sub(r'\2', remove_mk(v)) for k, v in ans.items()}
print(get_url(remove_inner_links(remove_stress(ans))))