󠄁󠄁福澤 諭吉(ふくざわ ゆきち、旧字体: 福󠄁澤 諭󠄀吉、天保5年12月12日〈1835年1月10日〉- 明治34年〈1901年〉2月3日)は、幕末から明治期の日本の啓蒙思想家、教育家。慶應義塾の創設者。諱は範(はん)。字は子圍(しい)。揮毫の落款印は「明治卅弐年後之福翁」。雅号は、三十一谷人(さんじゅういっこくじん)。
学問のすゝめ(學問ノスヽメ、がくもんのすすめ)は、福沢諭吉の著書のひとつであり代表作である。初編から17編までシリーズとして発行された。初編のみ小幡篤次郎共著。
1872年(明治5年2月)初編出版。以降、数年かけて順次刊行され、1876年(明治9年11月25日)十七編出版を以って一応の完成をみた。その後1880年(明治13年)に「合本學問之勸序」という前書きを加え、一冊の本に合本された。
import MeCab
import csv
import pandas as pd
import re
import matplotlib as mpl
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import japanize_matplotlib
import seaborn as sns
from wordcloud import WordCloud
from matplotlib import rcParams
from matplotlib.colors import Normalize
import warnings
warnings.filterwarnings('ignore', category=matplotlib.MatplotlibDeprecationWarning)
%matplotlib inline
学問のすすめのテキストファイルは青空文庫より拝借
MaCabファイルを作成する
with open("susume.txt") as file:
text = file.read()
# 全角スペースを削除
text = text.replace(' ', '')
# Mecab適応
mecab = MeCab.Tagger()
susume_mecab = mecab.parse(text)
len(susume_mecab.split())
susume = susume_mecab.split('\n')
print(susume[10:20])
print(len(susume_mecab.split('\n')))
## タブと改行を削除してリスト化
susume_list = [i.split('\t') for i in susume_mecab.split('\n')]
df_susume = pd.DataFrame(susume_list)
# データ確認
df_susume
55645行目のEOS以降は、及び5列目からは不要なのでデータを整理
df_susume = df_susume.iloc[:-2,:5]
df_susume.head()
4列目に品詞が複数存在しているのでハイフンで分ける
正規表現で品詞を分割
df_parse = df_susume[4].str.extract(r'(\w+)-?(\w+)?-?(\w+)?')
dfの必要部分と品詞データフレームを結合
df = pd.concat([df_susume.iloc[:,:4], df_parse], axis=1)
コラム名を追加
df = df.set_axis(['surface','read1','read2','base','parse1', 'parse2', 'parse3'], axis=1)
df
sns.set(font='IPAexGothic')
most_freq = df.surface.value_counts()[:20].sort_values()
my_cmap = cm.get_cmap('copper')
my_norm = Normalize(vmin=most_freq.min(), vmax=most_freq.max())
fig = plt.subplots(figsize=(12, 8))
ax = most_freq.plot(kind = 'barh',
color = my_cmap(my_norm(most_freq.values)),
alpha = .8
)
ax.bar_label(ax.containers[0], fontsize=12)
ax.title.set_size(24)
plt.title('頻出語 上位20',size=30)
plt.xlabel('回数', labelpad=15, size=18)
plt.ylabel("頻\n出\n語", labelpad=18, size=18, rotation=0, va='center')
plt.show()
def w_cloud(word_list, rank):
# ワードクラウドオブジェクトの作成
word_object = ','.join(word_list)
# フォントパスを指定
font = '/opt/anaconda3/lib/python3.9/site-packages/japanize_matplotlib/fonts/ipam.ttc'
# ワードクラウドを生成
wordcloud = WordCloud(font_path=font,
background_color="lightgray",
max_words = rank,
colormap = 'BrBG_r',
width = 600,
height = 400,
)
# ワードクラウドを可視化
wordcloud.generate(word_object)
return wordcloud.to_image()
w_cloud(list(df.surface.values), 300)
parse1_freq = df.parse1.value_counts().sort_values()
my_cmap = cm.get_cmap('copper')
my_norm = Normalize(vmin=parse1_freq.min(), vmax=parse1_freq.max())
fig = plt.subplots(figsize=(12, 8))
ax = parse1_freq.plot(kind = 'barh',
color = my_cmap(my_norm(parse1_freq.values)),
alpha = .8
)
ax.bar_label(ax.containers[0], fontsize=12)
ax.title.set_size(24)
plt.title('品詞別頻度',size=30)
plt.xlabel('語数', labelpad=15, size=18)
plt.ylabel("品\n詞\n名", labelpad=18, size=18, rotation=0, va='center')
plt.show()
df_par = df.groupby('parse1').value_counts()
df_par = pd.DataFrame(df_par)
df_par
def word_search(word,rank):
"""
品詞名と表示するランクを渡すとグラフを返す
"""
df_result = df[df.parse1.isin([word])]
freq = df_result.surface.value_counts()[:rank].sort_values()
_cmap = cm.get_cmap('copper')
_norm = Normalize(vmin=freq.min(), vmax=freq.max())
fig = plt.subplots(figsize=(12, (rank/4)+2))
ax = freq.plot(kind = 'barh',
color = _cmap(_norm(freq.values)),
alpha = .8
)
title = '頻出' + word + ' 上位' + str(rank)
y_label = "".join([i + '\n' for i in word])
x_label = '回数'
plt.title(title,size=30)
plt.xlabel(x_label, labelpad=15, size=18)
plt.ylabel(y_label, labelpad=18, size=18, rotation=0, va='center')
return plt.show()
word_search('名詞',20)
df_noun= df[df.parse1.isin(['名詞'])]
w_cloud(list(df_noun.surface.values), 500)
word_search('形容詞', 10)
df_adj= df[df.parse1.isin(['形容詞'])]
w_cloud(list(df_adj.surface.values), 500)
word_search('動詞',30)
df_verb= df[df.parse1.isin(['動詞'])]
w_cloud(list(df_verb.surface.values), 300)
word_search('代名詞', 10)
df_pronoun= df[df.parse1.isin(['代名詞'])]
w_cloud(list(df_pronoun.surface.values), 100)
# パターンを定義
pt = r'[一-龥]'
# パターンを含む語のみのリストを作成
kanji_list = [i for i in df.surface.values if re.compile(pt).findall(i)]
len(set(kanji_list))
4468種類を確認
リストからグラフ用のデータを作成
# pd.Seriesでカウントし、上位20に絞り、ソート
kanji = pd.Series(kanji_list).value_counts()[:20].sort_values()
my_norm = Normalize(vmin=kanji.min(), vmax=kanji.max())
fig = plt.subplots(figsize=(12, 8))
ax = kanji.sort_values().plot(kind = 'barh',
color = my_cmap(my_norm(kanji.values)),
alpha = .8
)
ax.bar_label(ax.containers[0], fontsize=12)
ax.title.set_size(24)
plt.title('漢字を含む頻出語 上位20',size=30)
plt.xlabel('回数', labelpad=15, size=18)
plt.ylabel("頻\n出\n語", labelpad=18, size=18, rotation=0, va='center')
plt.show()
漢字を含む上位1000語のワードクラウド出力
w_cloud(kanji_list, 1000)
# パターンを定義
pt = r'[ァ-ヶ]'
# パターンを含む語のみのリストを作成
kana_list = [i for i in df.surface.values if re.compile(pt).findall(i)]
len(set(kana_list))
kana = pd.Series(kana_list).value_counts()[:20].sort_values()
my_norm = Normalize(vmin=kana.min(), vmax=kana.max())
fig = plt.subplots(figsize=(12, 8))
ax = kana.sort_values().plot(kind = 'barh',
color = my_cmap(my_norm(kana.values)),
alpha = .8
)
ax.bar_label(ax.containers[0], fontsize=12)
ax.title.set_size(24)
plt.title('片仮名を含む頻出語 上位20',size=30)
plt.xlabel('回数', labelpad=15, size=18)
plt.ylabel("頻\n出\n語", labelpad=18, size=18, rotation=0, va='center')
plt.show()
片仮名の単語はそもそも少ない
w_cloud(kana_list, 50)
執筆時の思惑、心情を理解するため可視化
from PIL import Image
from pylab import *
import cv2
import numpy as np
import urllib.request
import requests
# 画像urlはwikipediaから拝借
# 福澤諭吉
url_face = 'https://upload.wikimedia.org/wikipedia/commons/1/1a/Yukichi_Fukuzawa_1891.jpg'
# 一万円札
url_bill = 'https://upload.wikimedia.org/wikipedia/commons/d/d5/10000_Yenes_%28Anverso%29.jpg'
お札の画像確認
im = Image.open(requests.get(url_bill, stream=True).raw)
im
お札画像のサイズを取得する
w, h = im.size
w, h
グレースケールで同じ大きさの画像を生成
blank_img = Image.new('L', (w, h))
blank_img.size
顔写真を取得
# urlから画像を取得
req = urllib.request.urlopen(url_face)
arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
# img変数に格納
# flag https://docs.opencv.org/3.4/d8/d6a/group__imgcodecs__flags.html
img = cv2.imdecode(arr, 0)
画像確認
Image.fromarray(img)
サイズ確認
Image.fromarray(img).size
[上から:下、左から:右] のピクセル値で指定
cropped_img = img[110:526, 80:500]
お札の画像に近くするためにサイズ調整 おおよそ80%でアスペクト比を保持
re_img = cv2.resize(cropped_img, dsize=None, fx=0.8, fy=0.8)
Image.fromarray(re_img)
サイズ確認
re_img.shape
二極化の閾値のバリエーションで比較して確認する
ret, img_t64 = cv2.threshold(re_img, 64, 255, cv2.THRESH_BINARY)
ret, img_t96 = cv2.threshold(re_img, 96, 255, cv2.THRESH_BINARY)
ret, img_t128 = cv2.threshold(re_img, 128, 255, cv2.THRESH_BINARY)
fig = plt.subplots(figsize=(18, 8))
plt.subplot(1, 4, 1)
plt.title('Original')
plt.imshow(re_img, cmap='gray')
plt.subplot(1, 4, 2)
plt.title('64')
plt.imshow(img_t64, cmap='gray')
plt.subplot(1, 4, 3)
plt.title('96')
plt.imshow(img_t96, cmap='gray')
plt.subplot(1, 4, 4)
plt.title('128')
plt.imshow(img_t128, cmap='gray')
plt.show()
閾値 96 あたりから微調整して最終確認
ret, gray = cv2.threshold(re_img, 90,255, cv2.THRESH_BINARY)
Image.fromarray(gray)
反転してマスクを作成
mask = cv2.inRange(gray, 0, 50)
Image.fromarray(mask)
# 配列からイメージ作成
mask_img = np.array(mask)
bg_img = np.array(blank_img)
concat_img = np.concatenate((bg_img, mask_img), axis=1)
concat_img.shape
# Image.fromarray(concat_img)
お札のサイズにトリミング
resized_mask = concat_img[0:333, 336:1036]
Image.fromarray(resized_mask)
リスト、語数、画像を入力値として渡す
def w_cloud_img(word_list, rank, mask):
word_object = ','.join(word_list)
font = '/opt/anaconda3/lib/python3.9/site-packages/japanize_matplotlib/fonts/ipam.ttc'
wordcloud = WordCloud(
mask = mask,
font_path = font,
background_color= 'rgb(249,245,198)', # 画像から紙幣に近い色をピッキング
colormap = 'copper',#'BrBG_r',
max_words = rank,
prefer_horizontal = 0.9999,
collocations=True,
contour_width= 5,
contour_color='rgb(111,99,75)' # 画像から使用色をピッキング
)
wordcloud.generate(word_object)
return wordcloud.to_image()
漢字を含む語のワードクラウド
# リスト、単語数、マスクでワードクラウドを作成
w_cloud_img(kanji_list, 1000, resized_mask)
すべての語によるワードクラウド
w_cloud_img(list(df.surface.values),5000, resized_mask)
マスクを生成する関数を定義
def creat_mask(url, threshold):
"""
画像のurlと閾値わたすと生成した画像マスクを返す
"""
req = urllib.request.urlopen(url)
arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
img = cv2.imdecode(arr, 0)
ret, gray = cv2.threshold(img, threshold, 255, cv2.THRESH_BINARY)
mask = cv2.inRange(gray, 0, 50)
return mask
紙幣の画像のマスクを作成してワードクラウドを適応すると、見にくい
w_cloud_img(list(df.surface.values), 1000, creat_mask(url_bill,80))
すべての名詞のワードクラウドをご本人様画像を使用して表示してみるとこのようになる
w_cloud_img(list(df_noun.surface.values), 15000, creat_mask(url_face,90))