Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

実践的テキストデータ分析の演習(基礎編)

この演習では,日本の歌謡曲の歌詞データを対象に分析を行う.

使用するデータは,山本がオリコンランキングから収集した歌謡曲の歌詞に関するものである. オリコンランキングは,日本で最も知名度のある音楽ヒットランキングである. オリコンランキングの一つに年間シングル売り上げランキングというものがあり,ある年のシングル曲売り上げを集計し,そのランキングを1968年から公開し続けている.

こちらのリンクからダウンロードできるファイルdata.zip内には,ある年度のシングル曲売り上げ上位30件の曲の歌詞の情報が記されたTSVファイルが1968年から2024年分まで納められている(歌詞提供サイトの都合上,一部の曲が抜け落ちている). TSVファイル名は{順位}_{アーティスト名}_{曲名}.tsvの形式となっている. 例えば,ダウンロードしたdata.zipファイルを解凍して得られるdata/tokenized/2024年のフォルダに格納された01_Snow Man_LOVE TRIGGER.tsvというファイルは,「2024年のシングル売り上げ1位はSnow ManがリリースしたLOVE TRIGGERという曲」についての歌詞情報が記録されている.

また,各TSVファイルには,ファイル名に関する曲の歌詞を品詞単位で分割し,分割された単語に関する情報が一行ごとに格納されている. 例えば,以下はdata/tokenized/2018/フォルダにある18_米津玄師_Lemon.tsvファイルの冒頭10行である.

夢	夢	名詞	一般
なら	だ	助動詞	*
ば	ば	助詞	接続助詞
どれほど	どれほど	副詞	一般
よかっ	よい	形容詞	自立
た	た	助動詞	*
でしょ	です	助動詞	*
う	う	助動詞	*
未だに	未だに	副詞	一般
あなた	あなた	名詞	代名詞

行は歌詞に出現した単語に対応しており,出現順に並んでいる. 各行のテキストは(見えないが)タブ文字(\t)で区切られており,左から順に

  • 活用形(歌詞中で実際に使われた形)

  • 原形(辞書に載る基本形)

  • 品詞(名詞・動詞など)

  • 品詞詳細(助詞・代名詞などの細分類)

に関する情報が入っている. 例えば,上の例では5行目の情報からは

  • 米津玄師作のLemonの歌詞で5番目に出現する単語は「よかっ」で

  • 品詞は「形容詞」,原形は「よい」である

ということが読み取れる.

準備

以下のコードを実行すると,演習で用いるファイルをダウンロードし,data/tokenizedフォルダにデータを展開できる. なお,ダウンロードしたzipファイルを解答するにはパスワードが必要となる. 教員からパスワードを入手すること

  1. data.zipファイルをまだダウンロードしていない人は,以下のコードを実行してください.

  2. data.zipファイルを既にダウンロードした人,あるいはファイルを自力でダウンロードする人は,以下の手順をスキップしてください.

import os
import requests
import zipfile

# ダウンロードURL
DATA_URL = 'https://www.ds.nagoya-cu.ac.jp/~yamamoto/download/jsong-lyrics/data.zip'

# パスワード
ZIP_PASSWORD = '******'

# データをダウンロード
print("[STEP] ダウンロード開始...")
downloaded_data = requests.get(DATA_URL).content
with open(f'data.zip', mode='wb') as f: # wb でバイト型を書き込める
  f.write(downloaded_data)

# Zipファイル解凍
print("[STEP] 解凍中...")
zip_data = zipfile.ZipFile('data.zip', 'r')
zip_data.extractall(path='.', pwd=ZIP_PASSWORD.encode())
zip_data.close()

# ゴミファイルの削除
print("[STEP] 余分ファイル削除中...")
for year in range(1968, 2025):
    for filename in os.listdir(f'data/tokenized/{year}'):
        if not filename.endswith('.tsv'):
            os.remove(f'data/tokenized/{year}/{filename}')

# ダウンロードしたzipファイルを削除
os.remove('data.zip')
print("[DONE] data/tokenized/ にTSVが展開されました。")
[STEP] ダウンロード開始...
[STEP] 解凍中...
[STEP] 余分ファイル削除中...
[DONE] data/tokenized/ にTSVが展開されました。

演習の進め方

上記を踏まえて,以下の課題に取り組みなさい.

課題コンテンツは以下の2種類の要素で構成されている:

  • 提出課題:実データを扱う本番問題(採点対象),全部で5つ

  • 練習問題:提出課題を解くための基礎練習

練習を飛ばして提出課題に挑戦しても構いません. 提出課題が難しいと感じる場合は,練習問題から順に進めるのが効果的です.


課題41

練習41-A: 文字列を区切る

学生に読んだ本を毎日記録し1週間ごとに報告するよう依頼した. 依頼の際,データ分析の都合上,読んだ本をカンマ(,)で区切って書くようお願いした. その結果,学生Xから先週読んだ本の情報について以下のような内容が送られてきた:

コンビニ人間,ノルウェイの森,変身,ノルウェイの森,夜は短し歩けよ乙女,コンビニ人間,ノルウェイの森

今,上記内容を以下のように変数textに格納したとしよう. textの内容をカンマで区切り,本の名前を要素とするリストbooksを作成するコードを書きなさい.

text = "コンビニ人間,ノルウェイの森,変身,ノルウェイの森,夜は短し歩けよ乙女,コンビニ人間,ノルウェイの森"
関連する事項: str.split
text = "コンビニ人間,ノルウェイの森,変身,ノルウェイの森,夜は短し歩けよ乙女,コンビニ人間,ノルウェイの森"

# Write your code below

練習41-B: 辞書データの作成(リストのループ/setdefault)

以下のリストは,学生Yが1週間に読んだ本のタイトルである. それぞれの本が何回読まれたかの情報について,変数book_frequencyに辞書型データとして格納しなさい.

books = ["ハリーポッター", "ハリーポッター", "進撃の巨人", "ワンピース", "進撃の巨人", "ワンピース", "ワンピース"]
関連する事項: リストのループ, dict.setdefault
books = ["ハリーポッター", "ハリーポッター", "進撃の巨人", "ワンピース", "進撃の巨人", "ワンピース", "ワンピース"]

# Write your code below
book_frequency = {}

練習41-C: 辞書のソート

練習41-Bで作成した辞書データを用いて,学生Yが読んだ本のタイトルと読書回数を回数が多い順に表示するコードを書きなさい.

関連する事項: sorted
# Write your code

☆課題41(提出課題)

2019年のシングル曲売り上げ上位30件(のファイル名)を調べ,ランキング30位以内に入った回数が最も多いアーティストを表示するコードを書きなさい.

関連する事項: os.listdir, リストのループ, str.split, dict.setdefault, sorted
# Write your code below
ヒント

指定したフォルダ(ディレクトリ)の中にあるファイルの一覧を取得するには,osモジュールのlistdir関数を使うとよい. 以下は,data/tokenized/2024という場所にあるフォルダ内にあるファイル一覧を取得するコードの例である.

import os

dir_path = 'data/tokenized/2024'
filenames = os.listdir(dir_path)

print(filenames)

課題42

練習42-A: リスト/辞書のループ

以下のデータは,いくつかの架空のスポーツ大会において優勝した大学の名前を年ごとにまとめたものである. ご覧の通り,変数resultsに格納されたデータは(Pythonの)辞書型データである.

results = {
    "2021": ["A大学", "B大学", "A大学", "C大学"],
    "2022": ["B大学", "B大学", "C大学", "A大学"],
    "2023": ["A大学", "C大学", "C大学", "D大学"]
}

変数resultsに格納されたデータを用いて,キーを「大学名」,値を「優勝回数」とする辞書型データfrequency_winを作成するコードを書きなさい.

関連する事項: 辞書のループ, dict.setdefault
results = {
    "2021": ["A大学", "B大学", "A大学", "C大学"],
    "2022": ["B大学", "B大学", "C大学", "A大学"],
    "2023": ["A大学", "C大学", "C大学", "D大学"]
}

# Write your code below
frequency_win = {}

練習42-B: 辞書のソート

練習42-Aで変数frequency_winに格納したデータを用いて,優勝回数の下位3大学を表示するコードを書きなさい.

関連する事項: sorted, スライスによるリストのアクセス
# Write your code below

☆課題42(提出課題)

1968年から2024年までのシングル曲売り上げ上位30件(のファイル名)を調べ,ランキング30位以内に入った回数が多いアーティストの上位10件を表示するコードを書きなさい.

関連する事項: range, os.listdir, str.split
import os

# Write your code below

課題43

練習43-A: ファイルの読み込み

こちらにあるファイル(fruit.txt)には次のような内容が書かれている:

りんご,440
バナナ,220
みかん,330
...

fruit.txtファイルをダウンロードした上で,ファイルの内容を1行ずつ読み込み,果物名をキー,数字(価格)を値とする辞書データを作成しなさい. 作成したデータは変数fruitsに格納しなさい(※ ダウンロードは手動で行えばよい).

関連する事項: ファイルの読み込み, str.split
fruits = {}

# Write your code below

練習43-B: 辞書のキーの一覧/文字列結合

練習43-Aで作成した辞書fruitについて,その辞書のキー(つまり果物名)をカンマ(,)で結合し,文字列として出力するコードを書きなさい.

関連する事項: dict.keys, str.join
# Write your code below

☆提出課題43

data/tokenized/1976フォルダにある01_子門真人_およげ!たいやきくん.tsvファイルを1行ずつ読み込み,単語の出現順に「活用形」を取り出しつなげることで,「およげ!たいやきくん」の歌詞を復元しなさい.

関連する事項: ファイルの読み込み, str.join
import os

# Write your code below

課題44

練習44-A: 辞書のループ/条件分岐

変数animalsは,動物とその分類に関する情報が格納された辞書である.

animals = {
    "犬": "哺乳類",
    "カエル": "両生類",
    "トカゲ": "爬虫類",
    "猫": "哺乳類",
    "ワニ": "爬虫類"
}

分類が哺乳類の動物だけを抽出し,その名前(動物名)を要素とするリストanimal_namesを作成するコードを書きなさい.

関連する事項: dict.items
animals = {
    "犬": "哺乳類",
    "カエル": "両生類",
    "トカゲ": "爬虫類",
    "猫": "哺乳類",
    "ワニ": "爬虫類"
}

animal_names = []

# Write your code below

練習44-B: 条件つきカウント

練習44-Aで用いた変数animalsにおいて,分類が「哺乳類」以外の動物の数をカウントするコードを書きなさい.

関連する事項: dict.items
animals = {
    "犬": "哺乳類",
    "カエル": "両生類",
    "トカゲ": "爬虫類",
    "猫": "哺乳類",
    "ワニ": "爬虫類"
}

# Write your code below

練習44-C: ファイルの読み込み,平均値の計算

ダウンロードした歌詞関連データ(data.zip)内にあるdata/songlist.tsvは,歌詞データセットの中で対象としている曲(つまりtokenizedフォルダ以下で取り扱われている曲)を一覧にしたTSVファイルである. このTSVファイルの各行には以下の情報がタブ文字(‘\t’: 不可視文字)区切りで記されている.

  • ランキング集計された年

  • ランキング順位

  • アーティスト名

  • 曲名

  • 感情スコア: 値が1に近いほど歌詞がポジティブ,-1に近いほど歌詞がネガティブ

songlist.tsvファイルを読み込み,1968年から2024年までの感情スコアの平均値の一覧を表示するコードを書きなさい.

関連する事項: ファイルの読み込み, str.split, int/float, dict.setdefault, リストのループ
# Write your code below

☆提出課題44

歌詞における代名詞の使用頻度を分析したい. 1968年から2024年までのランキングに入っている曲の歌詞から代名詞を抽出し,その代名詞が歌詞中で用いられている曲数を辞書型で格納しなさい(代名詞をキー,曲数を値とする辞書データを作成しなさい). また,使用頻度(使用されている曲数)が高い順に代名詞をソートし,その上位20件を表示しなさい.

※ 代名詞を抽出する際,以下の指示語は無視すること.

STOPWORDS = ['これ', 'それ', 'あれ', 'どれ', 'ここ', 'そこ', 'あそこ', 'どこ']
関連する事項: range, os.listdir, ファイルの読み込み, dict.items, dict.setdefault
import os

STOPWORDS = ['これ', 'それ', 'あれ', 'どれ', 'ここ', 'そこ', 'あそこ', 'どこ']

# Write your code below

課題45

練習45-A: 辞書の辞書/ループの入れ子

変数salesに格納されたデータは,年代ごとに商品A, B, Cが売れた個数を示している. 各商品の合計販売数を求めるコードを書きなさい(例: Aは18個).

sales = {
    1990: {"A": 10, "B": 5},
    2000: {"A": 3, "C": 8},
    2010: {"B": 7, "C": 10},
    2020: {"A": 5, "B": 2, "C": 3}
}
関連する事項: dict.items, dict.setdefault
sales = {
    1990: {"A": 10, "B": 5},
    2000: {"A": 3, "C": 8},
    2010: {"B": 7, "C": 10},
    2020: {"A": 5, "B": 2, "C": 3}
}

# Write your code below

練習45-B: 辞書ソート再び

練習45-Aで用いたデータにおいて,最も販売合計数が多い商品名とその数を出力するコードを書きなさい.

関連する事項: dict.items, dict.setdefault, sorted
# Write your code below

☆提出課題45

歌詞における言葉の使われ方は,社会や文化,時代ごとの流行を反映していると考えられる. そこでこの課題では,「僕」「君」といった一人称/二人称代名詞に着目したい.

以下のPRONOUNSに記した一人称/二人称代名詞について,注目する代名詞が出現する曲数を年代別に分析し,結果を表示しなさい. なお,「年代」のグルーピングは1960年代,1970年代,1980年代,1990年代,2000年代,2010年代,2020年代としなさい.

PRONOUNS = ["僕", "私", "僕ら", "俺", "わたし", "ぼく", "君", "あなた", "おまえ", "お前", "キミ"]
関連する事項: os.listdir, ファイルの読み込み, リストのループ, dict.items/keys, dict.setdefault, in, sorted
import os

PRONOUNS = ["僕", "私", "僕ら", "俺", "わたし", "ぼく", "君", "あなた", "おまえ", "お前", "キミ"]

# Write your code below