乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

プログラミング

新型コロナウイルス感染拡大に伴う
緊急経済対策の柱に位置付けられる
「現金30万円」の給付金。

これ貰えるのか貰えないのか
気になってしまったので実装してみました。

解説動画はこちら




聞いた話だと「給付条件」は段階があるようです。

1.世帯主の2~6月の月収が減り
以下の月収金額以下である場合は給付金は貰える

単身世帯…月収10万円
2人世帯…月収15万円
3人世帯…月収20万円
4人世帯…月収25万円

2.世帯主の2~6月の月収が1/2以下に減り
以下の月収金額以下である場合は給付金は貰える

単身世帯…月収20万円
2人世帯…月収30万円
3人世帯…月収40万円
4人世帯…月収50万円

段階があるのでちょいとややこしいですね。

今回はipywidgetsで実装してみました。

条件の目安にしていただく程度のものです
実際に貰えるかどうか等は
ご自身でご確認くださいませ。
from ipywidgets import IntSlider , interact

n1 = IntSlider(value=20, min=0, max=100, step=1,description='前年の月給')
n2 = IntSlider(value=20, min=0, max=100, step=1,description='今年の月給')
n3 = IntSlider(value=1  , min=1, max=4,      step=1,description='世帯人数')

def show_plot(n1, n2,n3):
    print('前年の月給 : {0}万円 , 今年の月給 : {1}万円 , 世帯人数 : {2}人'.format(n1,n2,n3))
    if any([(n3==1 and n2<=10),(n3==2 and n2<=15),(n3==3 and n2<=20),(n3==4 and n2<=25)]):
        print('給付金がもらえる(1)')
    elif (n2<=n1/2) and any([(n3==1 and n2<=20),(n3==2 and n2<=30),(n3==3 and n2<=40),(n3==4 and n2<=50)]):
        print('給付金がもらえる(2)')
    else:
        print('給付金は貰えない')

interact(show_plot, n1=n1,n2=n2,n3=n3)

実行していただくと、こんな感じになります。
スライダーを動かしていけば結果が出ます。

スクリーンショット 2020-04-12 16.05.24



結論から行くと
自分は貰えないんで、テンションだだ下がりです。

とはいえ、この条件であれば
家族が多ければ貰える人も結構いると思うので
条件に当てはまる方は
申し込みした方が良いですね。

申し込みする役所が
クラスターになる可能性も有るので
気を付けないといけないですが。

今回はこれまでです
それでは。


TKO木下の動画が絶賛炎上中だと聞きつけまして
早速コメントを感情分析してみました

解説動画はこちら


炎上している動画はこんな感じです。

動画タイトル:TKO木下よりご報告がございます。
公開日:2020/04/01
2020/04/11 16:00現在
視聴回数:2,845,395 回視聴
高評価:4771件
低評価:28万件
コメント数:50,898 件

素晴らしい低評価の数ですねー。
私は動画は見ておりませんが
低定評に1評投じさせていただきました。


さて
感情分析のやり方ですが
Youtubeのコメントと形態素解析
それと単語感情極性対応表というものを使います。

単語感情極性対応表は
こちらを参照してください。



中身はこんな感じで

ない:ない:助動詞:-0.999997
酷い:ひどい:形容詞:-0.999997
病気:びょうき:名詞:-0.999998
死ぬ:しぬ:動詞:-0.999999
悪い:わるい:形容詞:-1

ポジティブワード、ネガティブワードがあり
ポジティブ方向になると0から1点
ネガティブ方向は-1から0点の間の数値を取ります。

単語のポジネガ具合が分かる訳です。

手順としては

1.事前にYoutubeのコメントを集める。
  Youtubeの動画のページをスクロールして
  コメント表示させてから保存する。

 2.BeautifulSoupでHTMLの中から
  コメントの部分だけ拾い上げる。

3.コメントを形態素解析して単語感情極性対応表と
  比較してポジネガ点数をつける
  ポジティブだとプラス,ネガティブだとマイナスの点になる

まずはじめに
動画のコメントを集めなければならないので
動画のページをブラウザーで開いて
コメントを表示させたら、HTMLファイルに保存します。

次にPythonのコードを使って
HTMLの構文解析を行い、コメントを抽出します。

まず必要なライブラリは
from bs4 import BeautifulSoup
from janome.tokenizer import Tokenizer
t = Tokenizer()

janomeは後に使いますが、インストールしていない方は
pip などでインストールしておきましょう。

次にhtmlファイルを読み込んで変数に格納しておきます。
with open('htmlのファイル') as _f:
    html = _f.read()


お次はコメント部分の抽出です。
htmlファイルの中からコメントを抽出して
リストに格納しています。
soup = BeautifulSoup(html ,'lxml')
contents = soup.find('div',id='contents')
ytds = contents.find_all('ytd-comment-thread-renderer')
result_list = []
for ytd in ytds:
    span1 = ytd.find('span',class_="style-scope ytd-comment-renderer")
    name = span1.text.replace('\n','').replace(' ','') if span1 is not None else ''
    span2 = ytd.find('span',id="vote-count-middle")
    high = span2.text.replace('\n','').replace(' ','') if span2 is not None else ''
    come1 = ytd.find('yt-formatted-string', id="text")
    rep = come1.text.replace(' 件の返信を表示','').replace(' ','') if come1 is not None else ''
    come2 = ytd.find('div',id="content", class_="style-scope ytd-expander")
    com = come2.text.replace('\n','').replace(' ','') if come2 is not None else ''
    tmp = [name,high,rep,com]
    result_list.append(tmp)

次は形態素解析です。

単語感情極性対応表は事前にダウンロードしておいて
CSVファイルなどにしておいてください。

単語を辞書型に取り込みます。
posinega = {}
with open('posinega.csv') as _f:
    for row in _f:
        rows = row.replace('\n','').split(':')
        posinega[rows[0]] = float(rows[3])

最後にコメントを形態素解析して
ポジネガで点数をつけていきます。
nega_result = {}
for rows in result_list:
    count = 0
    for token in t.tokenize(rows[3]):
        h = token.part_of_speech.split(',')[0]
        if any(['名詞'==h,'形容詞'==h,'動詞'==h]):
            num=len(token.surface)
            key = token.surface
            if key in posinega:
                count+=posinega[key]
    nega_result[rows[3]]=count

これでコメントにポジネガの点数が付きました。

最もネガティブなコメントは・・・

-53.76871590000002
私は叙々苑でバイトをしていた者です。
1年前、TKO木下が私のバイト先東京の叙々苑を
訪れた際の記憶は忘れられません。 悪い意味で。
TKO木下は入店早々に既に様子がおかしく、
ホール担当だった私の胸ぐらを急に掴み一言。
「さっさと案内しろやボケ」と。
しかし木下が入店する所を見て3秒程で
駆けつけたのにも関わらすこの暴言暴力
・・・
辛いです。

と全文はかなり長いので端折りますが
冒頭を見るだけでもかなりネガティブさが伝わる文面です。

ネガティブの一番悪いものでも-1点なので
60個近くネガティブな単語が使われているコメントでした。

これだけの長文を想像で書くのは無理でしょうから
実体験だったんだろうと思いますね。

というようなネガティブコメントが多数並んでいました。

逆に
ポジティブなコメント有るんかな?
みてみましょう。

11.14069 ウケる笑笑低評価笑笑笑笑笑笑笑笑笑笑
2.890590 おはよう。くっさいなぁ~笑笑笑
2.530665 祝!低評価日本一更新!
1.666281 2倍速だと面白い
1.412733 朗報低評価日本一達成
1.374283 むしろコメ欄見にきてる笑日本一の低評価王にしてあげるためにみんな低評価押そうな
1.299542 宮迫博之の真似すれば売れるとおもったんやろ笑笑
1.261103 (*'∇')/゚・:*【祝】*:・゚\('∇'*)低評価日本一!よっ!!あっぱれ!流石です!!
0.989242 ヒカルを越した天才
0.989199 適当にやってもいいよ君が面白いと思っても多分面白くないから
0.989199 ff7本当に面白いよ😃
0.963530 なんかこんだけ荒れてることすらおいしいな〜とか思ってそう。笑 0.935754 大喜利コメ見てるから黙れ
0.932040 バチスタすごい好きでしたw
0.932040 本当にお笑いが好きならやらんやろアホか
0.921042 うちの姪が初めて掴まり立ちしましてね。みんなで喜びました。
0.769555 来世で頑張って下さい❗️来世で応援します‼️
0.650668 ファンのみなさま、、、っておるんか?(笑)
0.568479 低評価日本一おめでとう㊗️あと、誰に謝ってんねん
0.568479 おめでとう低評価日本一‼️
0.568479 低評価日本一おめでとうございます!
0.568479 低評価日本一おめでとナス!


低評価おめでとう、など
悪い意味で褒めてる感じですねwwwwww。

というわけで、まとめですが

日頃の行いは大事です。
見てない所でも敬意を払うことは当たり前だと思います。
特にタレントさんの私生活には
その人となりが出るようですね。

また素行の悪い方がテレビに出るのは
あまり良いことだとは思いません。

ネガティブなイメージの有るタレントをCMなどに使うと
商品、サービスにもネガティブイメージがつくので
我々企業側の人間はこういうタレントは
使わないようにしないといけないです。

ということで動画コメントの
感情分析でした。

皆様も
日頃の行いには気をつけたほうが良いですよ
誰がみてるか分かりませんし。

それでは


米失業保険申請者数のデータがあったので
可視化してみました。


解説動画はこちら



データはここにあります。

データソース:2020年03/28までの統計データ

米国労働省:

https://www.dol.gov/ui/data.pdf

アメリカ合衆国 労働省雇用管理局

https://oui.doleta.gov/unemploy/wkclaims/report.asp

これをcsvファイルにしておきます。
列は「N.S.A(日付)」「S.F.(申請数)」の2列分を用意します。




pandas を使ってデータを読み込みします。
import pandas as pd

df = pd.read_table("米失業申請者数データ20200328.csv")
df['day'] = pd.to_datetime(df['N.S.A'], format='%m/%d/%Y')
「N.S.A」列が日付の部分の文字列「m/d/y」形式になっているので
日付のデータに直します。

次に可視化ツールのplotlyの方ですが
普通はインストールされていないと思うので
インストールしていない方はpip install plotly
などでインストールしてください。

以下のコードがこのデータを可視化するコードです。
import plotly
plotly.offline.init_notebook_mode(connected=False)
data = [
    plotly.graph_objs.Scatter(x=df["day"], y=df["S.F."], name="Claims")
]
layout = plotly.graph_objs.Layout(
    width=1000, height=600,
    title="title",
    xaxis={"title":"Years"},
    yaxis={"title":"Claims"},
)
fig = plotly.graph_objs.Figure(data=data, layout=layout)
plotly.offline.iplot(fig, show_link=False) 

日付を横軸(x) , 申請者数を縦軸(y)にあてて
線グラフを作ります。

可視化の結果は・・・
スクリーンショット 2020-04-05 15.56.29

右上にplotlyのツール類が表示され、ズームインアウトや
選択など色々選んで操作できます。

一般的なpandas、matplotlibの可視化では
動かすことができないので
可視化された図表を動かして見ることのできる
plotlyはかなりの優れものです。

データの方を見てみると
1982年とリーマンショックのあった2009年に
かなり多くの申請があったことが見えました。

しかし2020年3月になると
ドーンと跳ね上がって・・・

スクリーンショット 2020-04-05 16.01.20

爆増しているのが見えます。
レポートの数値から見ると
失業申請者数は600万人を超えているみたいですね。

リーマンの時でさえ100万人に満たなかった訳で
今回の影響がどれだけヤバイのかがすぐにわかります。

このデータは3/28のデータ
今日は4/5なのでそこから1週間経ってるいるため
さらに倍増している可能性もあります。

一説によると
アメリカの労働人口の2割ほどが影響を受けているそうで
もし、日本でも同様の事態となると
数十万人 - 100万人単位で
影響を受ける方が増えると予想されます。

特にレストランやバー、映画館、ホテル、スポーツジム
などは営業停止しており
特定の製造業も工場の稼働停止をしています。

リーマンの時は稼働停止までは至っていなかったと思うので
10年前の大不況に比べると
はるかに大きな不況が目の前に来ています。

前回の余波は、自分も食らったので2年くらい
まともな仕事が無かったです。

今回、それを超えるようなことに
ならないことを願うばかりです。

エンジニアの対策としては
現状新規案件が白紙、撤回されたり
内定も取り消されるケースが増えているようです。

フリーランスになったり、転職活動は
かなり厳しくなると予想されるので
今雇用があるなら、そこでじっと騒動が収まるまで
耐えるしかないかなと思います。

頑張って乗り切れば
明るい未来が待っていると思いたい。

それでは。



 

グッバイ、イレーーギュラーーーーー
とか叫びたくなる今日この頃

なんとなく
Official髭男dismの歌詞の特徴を見てみたい
と思ってしまいました。

解説動画はこちら





はい
ひげだんさんの歌詞の特徴を見ていきたいですが
事前準備として
1.歌詞を集める
2.形態素解析する
3.テキストファイルにする

この作業が必要でーーーす。

これができましたら
以下のコードを試すことができます。

先ずは
ワードクラウドで歌詞の特徴を可視化する。

ワードクラウドは歌詞に出てくる単語の出現頻度順で
文字を大きさを決めて、1枚にまとめたものです。

コードは
from wordcloud import WordCloud
text_file = open('higedan_list.txt', encoding='utf-8')
text = text_file.read()

#fpath = 'C:/Windows/Fonts/meiryob.ttc'
fpath = '/System/Library/Fonts/ヒラギノ丸ゴ ProN W4.ttc'
stop_words = []
#stop_words = ['そう', 'ない', 'いる', 'する', 'まま', 'よう', 'てる','しまう','それ','なる', 'こと', 'もう', 'いい', 'ある', 'ゆく', 'れる']
wordcloud = WordCloud(background_color='white',font_path=fpath,width=800, 
  height=600, stopwords=set(stop_words),
                      regexp=r"[\w']+"
                     ).generate(text)
wordcloud.to_file('higedan.png')
plt.figure(figsize=(12,9))
plt.imshow(wordcloud)
plt.axis("off")
plt.show()

このコードではfpathでフォントの場所を指定しているので
お使いのマシンのパスにあわせてください。

ワードクラウドの結果は
higedan

する、僕、君
が大きいですねーーー

「僕と君がする」んでしょうね!!!!

何をするかは存じませんが
割と一般的な語句が多いようですね。

歌詞の特徴としてはそこまで
突拍子もない単語は連呼していない訳です。

次に単語の数ではなく
TF-IDFで重要そうな言葉を見てみます。

TF とは Term Frequency の略で、単語の出現頻度を表します。
IDF とは Inverse Document Frequency の略で、逆文書頻度を表します。

これを掛け合わせたものがTF-IDFで

ある単語が多くの文書で出現するほど値は下がり
特定の文書にしか出現しない単語の重要度を上げる役割をします。

TF-IDF値は0-1の間の値を取ります。
重要なキーワードは1に近づきます。

0.25より大きなワードを出してみました。

import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
np.set_printoptions(precision=2)

with open('higedan_list.txt','r') as _f:
    docs = [row.replace('\n','') for row in _f]

vectorizer = TfidfVectorizer() 
X = vectorizer.fit_transform(docs)

words = vectorizer.get_feature_names()
for did, vec in zip(range(len(docs)), X.toarray()):
    print('doc id : ', did)
    for w, tfidf in sorted(enumerate(vec), key=lambda x: x[1], reverse=True):
        if tfidf>0.25:
            wo = words[w]
            print('\t{0:s}\t{1:f}'.format(wo, tfidf))
doc id :  1
	love	0.721728
      ・・・
doc id :  43
	違う	0.329506
	グッ	0.327694
	バイ	0.296629
	もっと	0.265779

doc id1は最近佐藤健さんが主演したドラマの主題歌です。

loveという単語は
他の歌詞にはあまり使われていないけど
ここの歌詞では連呼されてるんでしょうねーー

tf-idf 閾値0.1にすると
「イレギュラー」も含まれてきます。

doc id43は映画の主題歌になった曲です。
「グッバイ」が特徴的な感じしますね。

最後にn-gramをみてみます。

n-gramとはn個の単語の繋がりを表す言葉で
3つの単語であればtrigramになります。
with open('higedan_list.txt','r') as _f:
    docs = [row.replace('\n','').split(' ') for row in _f]

def n_gram(st, n):
    return [st[i:i+n] for i in range(len(st)-n+1)]

counts = {}
for doc in docs:
    trigrams = n_gram(doc,3)
    for tri in trigrams:
        key = ''.join(tri)
        if key in counts:
            counts[key] +=1
        else:
            counts[key] = 1
for k,v in sorted(counts.items(),reverse=True,key=lambda x:x[1]):
    print(k,v)
metellme 16
StandByYou 15
tellmetell 14
・・・・

一番多かったのは英語の歌詞の繋がりでした。
かなり英語の歌詞を多用している感じがあります。

まとめると

・全体的に割と一般的な日本語を多く使用する。
・1つの歌詞でキーワードになるような単語がある
「グッバイ」「イレギュラー」
・割と英語を多用するところもある。

かなーと思います。

歌詞の特徴を見るには
他にもいろんな手法があると思いますが
比較的簡単な方法をご紹介しました。

皆さんもぜひ試してみてください。
それでは。

新型コロナウィルスの感染者増加が止まりません。

このまま行ったらどうなるのかを
データから予測してみました。


解説動画はこちら



さて
今回は予測モデルを使って未来の予測を行います。

用いるライブラリとしては
pandas
matplotlib
fbprophet
になります。

一番初めにデータを読み込んでみましょう。

pandasでデータの提供元(奥村研究所)から
ダウンロードしてデータ化します。
import matplotlib.pyplot as plt
import pandas as pd
%matplotlib inline

df = pd.read_csv("https://oku.edu.mie-u.ac.jp/~okumura/python/data/COVID-19.csv",
                 index_col='Date', parse_dates=['Date'])

これでデータフレームにデータが読み込まれます。

データは4列あるようです。

まずは感染者数の推移を見てみましょう。
df.iloc[0:,0:2].plot(figsize=(16,9))
plt.show()
download

直近での推移が爆裂していますね。
増加率も見てみましょう。
pandasの関数 pct_changeで増加率を算出できます。

df['diff_Global Confirmed'] = df['Global Confirmed'].pct_change()
df['diff_Global Deaths'] = df['Global Deaths'].pct_change()
plt.figure(figsize=(16,9))
plt.bar(df.index,df['diff_Global Confirmed'],alpha=0.3,label="Confirmed")
plt.bar(df.index,df['diff_Global Deaths'],alpha=0.3,label="Deaths")
plt.legend()
plt.show()
download-1

1月末ごろから
中国での大流行があったことが
みて取れます。


中国を抜かした世界の推移を見てみましょう。
別の列を用意してあげます。
df['Confirmed2']=df['Global Confirmed'] - df['China Confirmed']
df['Deaths2']=df['Global Deaths'] - df['China Deaths']
df.iloc[0:,6:8].plot(figsize=(16,9))
plt.show()

download-2

中国以外は3月の頭くらいから
急激に増えているようですね。

増加率も見てみると

df['diff_Confirmed2'] = df['Confirmed2'].pct_change()
df['diff_Deaths2'] = df['Deaths2'].pct_change()
plt.figure(figsize=(16,9))
plt.bar(df.index,df['diff_Confirmed2'],alpha=0.3,label="Confirmed")
plt.bar(df.index,df['diff_Deaths2'],alpha=0.3,label="Deaths")
plt.legend()
plt.show()
download

2月の手前に急激に増えた日がありますね。
ここら辺が起点になっているようです。

次に死亡率です。
df['Death Rate'] = df['Deaths2'] / df['Confirmed2']
plt.figure(figsize=(16,9))
plt.bar(df.index,df['Death Rate'],alpha=0.8,label="Death Rate")
plt.legend()
plt.show()
download-1

直近では5%近くなっていてどんどん上がってきてもいます。

このまま増え続けるとどうなるのか
感染者数の推移を予測してみます。
facebookのprophetを用います。

これはインストールをしないと使えないので
お気をつけください。
from fbprophet import Prophet
import warnings

warnings.simplefilter('ignore',)
model_df = df[['Confirmed2']]
model_df = model_df.reset_index()
model_df = model_df.rename(columns={'Date':'ds','Confirmed2':'y'})
model_df.head()
予測用のデータは
ds,yの2列を用意してあげます。
dsは日付、yは感染者数です。


ds
y
02020-01-204
12020-01-215
22020-01-2310
32020-01-2416
42020-01-2523


モデルを作ります。
model = Prophet()
model.fit(model_df)

最後に予測です。
予測したい日数分の空のデータフレームを用意します。

空のデータフレームを使って
学習したモデルで予測します。
future_df = model.make_future_dataframe(600)
forecast_df = model.predict(future_df)
model.plot(forecast_df)

可視化もできます。
結果は
スクリーンショット 2020-03-29 17.17.04

このままの推移が続くと
今年の終わりには600万人
来年の6月にはその倍くらいにはなっています。

すでに対策を始めていますので
ここまでにはならないと思いたいですが
不要不急の用事がない限りは
あまり出歩かない方が良いでしょうね。

死亡率も5%近くということで
20人のうち一人亡くなると考えると
無視できない確率かなと
個人的には思います。

リモートワークが続いて
ずっと家にいるわけですが

早く
収束してくれることを
願うばかりであります。


このページのトップヘ