悩みすぎた男の末路

## 悩みすぎる男
私は国内のとある大学院博士課程に所属するアラサーの学生です

そして自他ともに認める優柔不断な人間でもあります

ラーメン屋の前でラーメンにしようかつけ麺にしようか悩み、Google Mapを開いてそれぞれの写真を確認した上で「一旦落ち着いて考えよう」と思ってラーメン屋の区画を一周するくらいには優柔不断です

![man](https://1.bp.blogspot.com/-vrd21CV1odc/Ut0BfeYTrQI/AAAAAAAAdZ0/XKMfGFdkPNg/s400/wakaremichi_man.png)

何につけてもこんな感じなので、**私は悩みを自覚するとEvernoteを開いて、自分が今何に悩んでいるのか、どうしたらそれが解決できるのかを言葉にして書き出すという習性があります**
もちろんそれは誰かに見せるためのものではなく、ただ自分の悩みを言語化して少しでも問題を客観的に整理できるようにするためです

こんな習慣を2018年の2月から始めてもう5年になりました
これまでに執筆した悩みノートの総数は2023年1月時点で1,620個です

平均すると一日あたり0.89 個の悩みが生まれている計算ですが、別に1日1回書くと決めているわけではなく、悩みがあったときにその分だけノートを追加するスタイルです
なので悩みが多くノートをたくさん書いている月もあれば、相対的に悩みの少ない時期もあります

![timeline.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176789/409ace28-fe73-f180-4713-b2bd9934c8b1.png)

しかしこうして振り返ってみると、悩みが完全になくなった時期というのはこの５年間で一回もないわけで、こうなってくると

:::note
悩みの原因は外部（環境）にあるのではなくて内部（自分の性格や認知）にあるのではないか？
:::

という疑いが濃厚になってきます

つまり悩みを根本的に解決するためには、**今抱えている問題について悩むのではなく、悩んでいる自分について考える必要があるのではないか**、ということです

そして私はひらめきました

:::note
自分の悩みについてのデータがこれだけあれば、自分の悩みを可視化して、自分がどのようなことに悩んでいるのか客観的に考察できるのではないか
:::


と

そう思った私は、数年前に研究で使ったテキストマイニングの手法を使って自分の悩みを計量的に分析することにしてみました

## やりたいこと
今回テキストマイニングを用いて答えたい問題は以下の二つです

:::note
1. 自分の悩みにはどのような単語がよく出てきるのか？
2. 自分の悩みにはどのようなトピックがよく現れるのか？
:::

この二つの問いを通じて**自分の悩みについてメタ的な視点を得ること**を今回の分析の目標とします

## やったこと
自分の悩みを分析するために私が行ったことは以下の三つです

:::note
1. Evernote からデータを取り出す
1. 取り出したデータを整形する
1. データを集計して可視化する
:::

いかに各ステップの具体的な方法を記述します

#### 1. Evernote からデータを取り出す
PC版Evernoteアプリを使ってデータを取り出します
WEB版ではダウンロードできないようなのでPC版アプリを使ってください

データの形式はhtmlも選べますが、今回はEvernoteの独自仕様であるenex形式でダウンロードしました

![スクリーンショット 2023-01-04 0.22.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176789/241859be-4fc9-7c32-6676-87fc18185365.png)

enex形式はevernote独自のxmlで記述されたテキストファイルです

<title>タグでノートのタイトル、<content>タグでノートの内容が記述されています

テキストのみであれば軽量です

私の場合は1,622個のノートで合計1.8MBでした

#### 2. 取り出したデータを整形する

今回はPythonのBeautifulsoupを使って整形しました

タイトル、コンテンツ、作成日時を Pandas の Dataframe でまとめるところまでは以下の通りです

```py
import pandas as pd
from bs4 import BeautifulSoup

# 前処理用の関数
import re
# as per recommendation from @freylis, compile once only
CLEANR = re.compile('<.*?>') 

def cleanhtml(raw_html):
  cleantext = re.sub(CLEANR, '', raw_html)
  return cleantext

# ファイルの読み込み
file = "[filename].enex"
with open(file) as f:
  soup = BeautifulSoup(f, "xml")

df = {"title":[], "content": [], "created_at": []}

# タイトルを取り出す
titles = soup.find_all("title", string=True)
for title in titles:
  df["title"].append(title.get_text())

# 本文を取り出す
contents = soup.find_all("content", string=True)
for content in contents:
  df["content"].append(cleanhtml(content.get_text()))

# 作成日時を取り出す
created_at = soup.find_all("created", string=True)
for time in created_at:
  df["created_at"].append(time.get_text())

```

続いてcontentカラムから形態素解析モジュール janome を使って単語を切り出していきます

```py
from janome.tokenizer import Tokenizer
from janome.analyzer import Analyzer
from janome.tokenfilter import *
from janome.charfilter import *

char_filters = [UnicodeNormalizeCharFilter(), RegexReplaceCharFilter(r"[IiⅠｉ?.*/~=()〝 <>:：《°!！!？（）-]+", "")]
tokenizer = Tokenizer()
token_filters = [POSKeepFilter(["名詞"]), POSStopFilter(["名詞,非自立", "名詞,数", "名詞,代名詞", "名詞,接尾"]),LowerCaseFilter()]
analyzer = Analyzer(char_filters=char_filters, tokenizer=tokenizer, token_filters=token_filters)

df.loc[:,'words'] = df.content.apply(lambda x: " ".join([token.surface for token in analyzer.analyze(x)]))
```

この辺りは以前Qiitaに書いた記事がありますのでよろしければこちらもどうぞ

https://qiita.com/kromiii/items/42273d805c7ddf5a64d2


#### 3. データを集計して可視化する
ここまででようやくデータの下処理が完了しました
まずは単純に出現頻度の多い単語をピックアップしてワードクラウドで可視化してみましょう

```py
from wordcloud import WordCloud

text = " ".join(df.words)
wordcloud = WordCloud(font_path = '/usr/share/fonts/truetype/fonts-japanese-mincho.ttf',
                      background_color="white",
                      collocations=False,
                      random_state=42,
                      max_words=50,
                      colormap="gnuplot2",
                      width=1000,height=400).generate(text)
import matplotlib.pyplot as plt
plt.figure(figsize=(15,12))
plt.imshow(wordcloud)
plt.axis("off")
```

結果は下記のようになりました
個人情報に関わる単語はあらかじめstopwordsで除外してあります

![wordcloud_50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176789/7be7bca3-7cd6-0a40-fe4a-db227d1b9c42.png)


出現頻度の高い単語ほど大きく表示されています

出現回数の多い単語としては「自分」や「研究」「時間」「お金」という単語になりますね。左の「X」というのは私が参加している研究プロジェクトの名前の一部です。

「結婚」や「博士」「生活」などは自分の年齢や肩書きを考えると、さもありなんという感じです

さて、ではもう少しこの結果を深掘りしていきましょう
今回はトピックモデルを使って単語をカテゴリごとに分類してみます

こちらの記事を参考にしています

https://towardsdatascience.com/topic-modeling-for-everybody-with-google-colab-2f5cdc99a647

```py
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer
from sklearn.decomposition import NMF, LatentDirichletAllocation
import numpy as np

no_topics = 5
no_top_words = 4 
no_top_documents = 3 

def display_topics(H, W, feature_names, documents, no_top_words, no_top_documents):
    for topic_idx, topic in enumerate(H):
        print("Topic %d:" % (topic_idx))
        print(" ".join([ (feature_names[i] + " (" + str(topic[i].round(2)) + ")")
          for i in topic.argsort()[:-no_top_words - 1:-1]]))
        top_doc_indices = np.argsort( W[:,topic_idx] )[::-1][0:no_top_documents]

documents = list(df.words)

# NMF is able to use tf-idf
tfidf_vectorizer = TfidfVectorizer(max_df=0.95, min_df=2, stop_words=stopwords)
tfidf = tfidf_vectorizer.fit_transform(documents)
tfidf_feature_names = tfidf_vectorizer.get_feature_names()

# Run NMF
nmf_model = NMF(n_components=no_topics, random_state=1, alpha=.1, l1_ratio=.5, init='nndsvd').fit(tfidf)
nmf_W = nmf_model.transform(tfidf)
nmf_H = nmf_model.components_

print("NMF Topics")
display_topics(nmf_H, nmf_W, tfidf_feature_names, documents, no_top_words, no_top_documents)
print("--------------")
```

結果はこのようになりました

| トピック | 中心的な単語 |
|:-:|:-:|
|  トピック１ | 自分、他人、幸せ、人生  |
|  トピック２ | 研究、論文、先生、博士 |
|  トピック３ | 結婚、好き、気持ち、恋愛 |
|  トピック４ | 時間、仕事、論文、無駄 |
|  トピック５ | お金、バイク、執着、貯金 |

各トピックに名前をつけるとすれば、トピック１は「人生一般」、トピック２は「研究」、トピック３は「結婚・恋愛」、トピック４は「仕事と効率化」、トピック５は「お金」となるでしょうか。

## 結果の考察
#### Q1: 自分の悩みにはどのような単語がよく出てくるのか？
色々な単語がありましたが、一番目を引く単語は **「自分」** という単語の登場回数の多さです

つまり**私の悩みの大半は私自身についての悩み**であり、家族や友達、恋人のことを心配しての悩みではありませんでした

恥ずかしい話ですが、私はこれをみていかに自分が自己中心的な人間だったのか気付かされました

最近読んだ本でD.カーネギーの『道は開ける』（原題：How to stop worrying and stop living）という本があります

https://amzn.asia/d/5vkJM3k

この本には悩みを止めるためのいくつかの処方箋が紹介されているのですが、その中にうつ病の患者に対してアドラーが言ったとされる以下のような言葉が紹介されています

> この処方どおりにしたら、二週間できっと（うつ病は）全快しますよ
> それはどうしたら他人を喜ばすことができるか、毎日考えてみることです
（pp. 247)（括弧内筆者）

その理由は、アドラーによれば**悩み・恐怖・抑うつの根源となっているものは自分自身であり、他人を喜ばそうとすることによって、これらのことについて考えなくなる**からだとされています

このアドラーの抑うつについての考え方は、賛否両論があると思いますし、個人的には本当にうつで苦しんでらっしゃる方には当てはまらないと思います

それでも今回の私の事例について言えば、思考のベクトルがあまりにも自分に向きすぎていたことが悩みの原因だという仮説が立てられそうです

#### Q2: 自分の悩みにはどのようなトピックが含まれるのか？
トピックモデルの結果から、私の悩みは「人生一般」「研究」「結婚・恋愛」「仕事と効率化」「お金」の五つのカテゴリーに分類されることが示唆されました

こういった人生の悩みの分類に関する先行研究にどのようなものがあるのか私は詳しくないのですが、「悩みのカテゴリー」で Google 検索した限りだとメンタリスト DaiGo さんの提唱した**HARM理論**というのがあるみたいです

https://salaryman-plus.com/side-business/law-of-harm

これによれば人間の悩みの大半は **H: Health (健康）A: Ambition （夢・キャリア）R: Relation （人間関係）M: Money （お金）** という四つのカテゴリに分類されるそうです

今回の私の例に当てはめると「人生一般」「恋愛」は R（人間関係）に、「研究」「仕事と効率化」は A （夢・キャリア）に、「お金」はM（お金）に分類されます

すると私の悩みには決定的に欠けているカテゴリが一つあることがわかります

それは **「健康」** です

そう、確かに私はこの５年間、多少体調を崩すことはあっても、大病を患ったこともなく、入院や手術を必要とする病気や怪我にかかったこともありません

これを幸運と呼ばずしてなんと言うのでしょうか

いつだって幸福は当人が当たり前だと思っていることの中にあります

私にとっては「健康」がまさにその一つでした

トピックモデルによる悩みの分析は私にそのことを気づかせてれたのではないでしょうk

## おわりに〜悩みすぎた男の末路
「恥の多い生涯を送って来ました」とは太宰治『人間失格』の冒頭の言葉です

そういう意味ではこの記事の内容は私の恥そのものです

この記事を書いたあと、こんな記事を公開して一体何になるのか悩みました [^1]

しかしこの結果自体は一般化が難しいとしても、この記事で用いた方法論自体は多くの人にとって有用なのではないかと思い、今回Qiitaに投稿することにしました

もはやライフワークと化した「悩むこと」をEvernoteに書き起こして５年間続けた先にあったのは、**自己中心的な自分の姿と自分が当たり前だと思って忘れている幸せへの気づき**でした

**自分と同じくらい他人をどうすれば喜ばせられるかを考えること、そして幸せはすでに自分が持っているものの中にあるということ**、Evernote を使った悩みのテキストマイニングはそんな人生のシンプルなルールを私に教えてくれたのかもしれません

この記事が私のような悩みすぎる人間の手助けとなれば幸いです

[^1]:この悩みについての記事自体も悩みの種になっているという再帰構造に注意