経済指標グラフを altair で表示 その2

経済指標グラフを altair で表示 その2

investpy で経済指標を取得し
altair で表示する

import pandas as pd
import investpy
import altair as alt
import datetime

economic_data = investpy.economic_calendar(time_zone=None, time_filter='time_only', countries=['japan', 'united states'], from_date='01/01/2021', to_date='11/06/2021')

ISM =economic_data[economic_data['event'].str.contains('ISM Non-Manufacturing PMI')]

date2 =[]
for i in ISM['date']:
    new_date = datetime.datetime.strptime(i,"%d/%m/%Y").strftime("%Y-%m-%d")
    date2.append(new_date)

ISM['date']=ISM['date'].str.replace('/','-')
ISM['date'] = date2
ISM.fillna(0)

chart =(
    alt.Chart(ISM)
    .mark_line(opacity=0.8,clip=True)
    .encode(
        x="date:T",
        y=alt.Y("actual:Q",stack=None)
    )
)

chart

とすると
ISM の actual の数値が折れ線グラフで表示される

実際の値だけでなく予測値の forecast もほしいので

actual =(
    alt.Chart(ISM)
    .mark_line(opacity=0.8,clip=True)
    .encode(
        x="date:T",
        y=alt.Y("actual:Q",stack=None)
    )
)

forecast =(
    alt.Chart(ISM)
    .mark_line(opacity=0.8,clip=True,color='red')
    .encode(
        x="date:T",
        y=alt.Y("forecast:Q",stack=None),       
    )
)

として2つの折れ線データを用意する

あとは
alt.layer で重ねて表示すると2つ表示される

alt.layer(actual,forecast).resolve_scale(
    y = 'independent'
)

independent を指定するとy軸が独立した2つになる

なお重ねて表示するのは3つでも可能

試しに previous の値も追加するのなら

previous =(
    alt.Chart(ISM)
    .mark_line(opacity=0.8,clip=True,color='green')
    .encode(
        x="date:T",
        y=alt.Y("previous:Q",stack=None),       
    )
)

alt.layer(actual,forecast,previous).resolve_scale(
    y = 'independent'
)

とすれば3つの折れ線グラフが表示される

重ねて折れ線グラフを表示するのについては
Layered chart with Dual-Axis

を参考に

altair で線の色を指定するには
altairでとあるアイドルグループのメンバー在籍期間のチャート化してみた

を参考に

最初に
altair.encode() で指定したときにはエラーとなった

color=
で指定するとラベル指定となってしまうらしい

経済指標グラフの日付問題

経済指標グラフの日付問題

形式が
dd/mm/yy
となっているので
altairで表示が月と間違えて表示される

月の表示を英語にすればいけるかもしれない

株価可視化複数アプリでそうしたので

import pandas as pd
import investpy
import altair as alt

economic_data = investpy.economic_calendar(time_zone=None, time_filter='time_only', countries=['japan', 'united states'], from_date='01/01/2021', to_date='11/06/2021')

economic_data2 = investpy.economic_calendar(time_zone=None, time_filter='time_only', countries=['japan', 'united states'], from_date='01/01/2021', to_date='31/01/2021')

ISM =economic_data[economic_data['event'].str.contains('ISM Non-Manufacturing PMI')]

chart =(
    alt.Chart(ISM)
    .mark_line(opacity=0.8,clip=True)
    .encode(
        x="date:T",
        y=alt.Y("actual:Q",stack=None)
    )
)
chart

これだと
dd/mm/yy
の mm 部分を日付と間違えるようだ

インタラクティブなデータの視覚化

をみたところ
プロット
のところで
プロットに使用する列が正しいデータ型であり、日付が(YYYY-MM-DD)の形式であることを確認しました。そのために、高価格列と低価格列をdoubleデータ型に変換し、日付列を文字列形式に変換しました。続いて、日付列をDD / MM / YYYY形式からYYYY / MM / DDに変換し、最後にYYYY-MM-DDに変換しました。
をみて

import plotly.graph_objs as go
from plotly.offline import init_notebook_mode, iplot
init_notebook_mode(connected=True)
import plotly.plotly as py
import plotly
import pandas as pd
import datetime

df = pd.read_csv("TSLA.csv")

df['date'] = df['date'].astype('str') 
df['high'] = df['high'].astype('double')
df['low'] = df['low'].astype('double') 

date2 = []
for i in df['date']:
    new_date = datetime.datetime.strptime(i, "%d/%m/%Y").strftime("%Y-%m-%d")
    date2.append(new_date)
    
df['date'] = df['date'].str.replace('/', '-')
df['date'] = date2
df.fillna(0)
df.head()

のうち

df = pd.read_csv("TSLA.csv")

df['date'] = df['date'].astype('str') 
df['high'] = df['high'].astype('double')
df['low'] = df['low'].astype('double') 

date2 = []
for i in df['date']:
    new_date = datetime.datetime.strptime(i, "%d/%m/%Y").strftime("%Y-%m-%d")
    date2.append(new_date)
    
df['date'] = df['date'].str.replace('/', '-')
df['date'] = date2
df.fillna(0)
df.head()

をみたところ
date の部分をループさせて
date2 に格納
date の値を date2 に書き換えて
df.fillna で反映しているみたいだ

df.fillna は欠損値の置き換えらしい

とりあえず実験

date2 =[]
for i in ISM['date']:
    new_date = datetime.datetime.strptime(i,"%d/%m/%Y").strftime("%Y-%m-%d")
    date2.append(new_date)

とすれば

date2 に

['2021-01-08',
 '2021-02-04',
 '2021-03-04',
 '2021-04-05',
 '2021-05-05',
 '2021-06-03']

と格納される

あとは代入すればいけると思って

ISM['date']=ISM['date'].str.replace('/','-')
ISM['date'] = date2
ISM.fillna(0)

としたら

<ipython-input-15-e3cb61543e3a>:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  ISM['date']=ISM['date'].str.replace('/','-')
<ipython-input-15-e3cb61543e3a>:2: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  ISM['date'] = date2

と警告がでる

これで

chart

とすればいちおう望み通りのグラフにはなる

エラーを

<ipython-input-15-e3cb61543e3a>:2: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

で検索してみたら
pandas の SettingWithCopyWarning で苦労した話

にその原因っぽいのが乗っていた

元のデータの一部を抽出→そのうち一部へ代入した場合、「元のデータのその部分」を修正したかったのか、「一部を変更した新しいデータ」を作りたかったのかどっちかわからないよ、という感じ
らしい

PandasのSettingWithCopyWarningに対する対処方法

も参考にしてみた

view か copy かを明確にしないとダメで
copy なら元の DataFrane は変更されない
view だと元まで変更となる

python で経済指標の取得とグラフ化その2

python で経済指標の取得とグラフ化その2

ISM Manufacturing PMI
ISM製造業PMI

altair でグラフにする

economic_data[economic_data['event'].str.contains('ISM Non-Manufacturing PMI')]

で結果の取得はできた

以前
apple の情報を取得し
そこから特定のカラムの Close だけ取り出したことがあるので

economic_data[economic_data['event'].str.contains('ISM Non-Manufacturing PMI')]['actual']

とすると

99      57.2
535     58.7
1016    55.3
1566    63.7
2027    62.7
2540    64.0
Name: actual, dtype: object

となり
ID と actual の数値がでる

ただし

chart =(
    alt.Chart(ISM)
    .mark_line(opacity=0.8,clip=True)
    .encode(
        x="Date:T",
        y=alt.Y("Stock Prices(USD):Q",stack=None),
        color='Name:N'
    )
)
chart

としてもエラーになる

ISM.dtype

を実行すると

dtype('O')

となる

検索して調べてみた
dtype( ‘O’)とは何ですか?

によれば
python object
とのこと

なので数値にしないとダメ
おそらくやり方が違っているので
株価可視化アプリでやったことを思い出す

economic_data.columns

でカラムを調べると

Index(['id', 'date', 'time', 'zone', 'currency', 'importance', 'event',
       'actual', 'forecast', 'previous'],
      dtype='object')

となる

過去に apple の株価取得したときには

Index(['Open', 'High', 'Low', 'Close', 'Volume', 'Dividends', 'Stock Splits'], dtype='object')

だった

今回は指標を絞ってみる

ISM =economic_data[economic_data['event'].str.contains('ISM Non-Manufacturing PMI')]
ISM.columns

とすると

Index(['id', 'date', 'time', 'zone', 'currency', 'importance', 'event',
       'actual', 'forecast', 'previous'],
      dtype='object')

となる
あまり変わっていない

ISM.reset_index()

でインデックスを振りなおしてみる

ism_act = ISM[['actual']]
ism_act


actual へ絞り込みができた

ただし、そのまま

chart =(
    alt.Chart(ism_act)
    .mark_line(opacity=0.8,clip=True)
    .encode(
        x="Date:T",
        y=alt.Y("Stock Prices(USD):Q",stack=None)
    )
)

としても日付がないので表示できない

pandas.DataFrameから条件を満たす行名・列名の行・列を抽出(選択)

を参考に

ism_act = ISM.filter(items=['date','actual'])
ism_act

とすれば日付も取得できる

chart =(
    alt.Chart(ism_act)
    .mark_line(opacity=0.8,clip=True)
    .encode(
        x="date:T",
        y=alt.Y("actual:Q",stack=None)
    )
)

ででたけど
表示がおかしい

原因は日付表示

99 	08/01/2021 	57.2
535 	04/02/2021 	58.7
1016 	04/03/2021 	55.3
1566 	05/04/2021 	63.7
2027 	05/05/2021 	62.7
2540 	03/06/2021 	64.0

の場合日付を月と認識されるので
表記を変える必要がある

ism_act.index = ism_act.index.strftime('%d %B %Y')

としたが

AttributeError: 'Int64Index' object has no attribute 'strftime'

となる

[Python]pandasの日付データから年、月、日、曜日への変換方法

を参考に

ism_act['date'] = pd.to_datetime(ism_act['date'],format='%Y-%m-%d')

としたがエラー
Pandasデータフレームを日付で並べ替え

を参考に

ism_act['date']=pd.to_datetime(ism_act.date)
ism_act.sort_values(by='date')

とすれば
ソートはできるが日付フォーマットを修正しないとバグる

df_ism_act = pd.DataFrame(ism_act)


Dataframe にしてみたが
おそらく株価アプリのときみたいに
DatetimeIndex を作成したほうがいいかもしれない

ism_act['date']=pd.to_datetime(ism_act['date'], format='%Y%m%d')
ism_act.sort_values(by='date')

だと
08/01/2021
を8/1
として認識して変換している

python で経済指標の取得とグラフ化

python で経済指標の取得とグラフ化

経済指標を取得しグラフ化することで
ニュース発表時の期待値との乖離を理解しやすくなる

まずは経済指標の値を取得

できればあとは
dow index
gold
WTI
なども取得できるようにする

jupyter-notebook
で実験をしてそれから
streamlit で表示
というコンセプトで

FXで重要な経済指標をWebスクレイピングで取得する方法

[Python]investpyで株、為替、経済指標データを取得する

を参考に

investpy
をインストール

!pip install investpy


jupyter notebook でインストールできる

investpyで世界の株価データを取得してみた

も参考に

import pandas as pd
import investpy

で必要なライブラリをインポート

code = '7203' #トヨタ自動車
stock_data = investpy.get_stock_historical_data(stock=code, country='japan', from_date='01/02/2021', to_date='28/03/2021')
stock_data.tail(5)

とすると

2021/2/1 から 2021/3/28
までのトヨタ自動車の株価を取得して表示できる

investpy.get_stock_historical_data


企業シンボルを stock=
国を country=
期間を from_date=, to_date
で指定する

これを APPle にするなら

symbol = "AAPL" #アップル
stock_data = investpy.get_stock_historical_data(stock=symbol, country='united states', from_date='01/02/2021', to_date='28/03/2021')
stock_data.tail(5)

とすればOK

違いはstock= を symbol にして

contury= を united states

にしていること

なお指定期間の為替の取得も可能

usd_jpy = investpy.get_currency_cross_historical_data(currency_cross='USD/JPY', from_date='01/02/2021', to_date='28/03/2021')
usd_jpy.tail(5)


from_date と to_date
で指定した期間の為替情報を

get_currency_cross_historical_data()

で取得している

currency_cross= で通過ペアの指定をしている

次に経済指標

investpy.economic_calendar

で各国の経済指標を得ることができる

economic_data = investpy.economic_calendar(time_zone='GMP +9:00', countries=['japan', 'united states'], from_date='01/02/2021', to_date='28/03/2021')
economic_data.tail(5)

だと

ValueError                                Traceback (most recent call last)
<ipython-input-16-10b765be85cc> in <module>
----> 1 economic_data = investpy.economic_calendar(time_zone='GMP +9:00', countries=['japan', 'united states'], from_date='01/02/2021', to_date='28/03/2021')
      2 economic_data.tail(5)

~/anaconda3/lib/python3.8/site-packages/investpy/news.py in economic_calendar(time_zone, time_filter, countries, importances, categories, from_date, to_date)
     80     else:
     81         if time_zone not in cst.TIMEZONES.keys():
---> 82             raise ValueError("ERR#0108: the introduced time_zone does not exist, please consider passing time_zone as None.")
     83 
     84     if not isinstance(time_filter, str):

ValueError: ERR#0108: the introduced time_zone does not exist, please consider passing time_zone as None.

となる

github で調べたら
https://github.com/alvarobartt/investpy/search?q=economic_calendar
にあるように

def economic_calendar(time_zone=None, time_filter='time_only', countries=None, importances=None, categories=None, from_date=None, to_date=None):

と定義されている

さらに詳細を
https://github.com/alvarobartt/investpy/blob/f7f43c4458a155237321528c9a46e2aa4a3e824d/investpy/news.py
で確認

        time_zone (:obj:`str`, optional): 
            time zone in GMT +/- hours:minutes format, which will be the reference time, if None, the local GMT time zone will be used.
        time_filter (:obj:`str`, optional):
            it can be `time_only` or `time_remain`, so that the calendar will display the time when the event will occurr according to 
            the time zone or the remaining time until an event occurs.

とあるので約してみると

time_zone(:obj: `str`、オプション):
GMT +/-時間:分形式のタイムゾーン。これが参照時間になります。[なし]の場合、ローカルGMTタイムゾーンが使用されます。
time_filter(:obj: `str`、オプション):
それは「time_only」または「time_remain」にすることができ、カレンダーはイベントが発生する時間を表示します
タイムゾーンまたはイベントが発生するまでの残り時間。

ということなので

economic_data = investpy.economic_calendar(countries=['japan', 'united states'], from_date='01/02/2021', to_date='28/03/2021')
economic_data.tail(5)

というように
time_zone を省略したらできた

次に

economic_data[economic_data['importance']=='high']

というように
importance カラムが high になっているものだけを抽出すれば
重要指標のみ表示ができる

actual
が実際の値

forecast が予測値
previousが前回の値

つまりこの3つのうち
forecast
previous
でグラフを作成、もしくは該当する経済指標でグラフを作成すればいい

とりあえずグラフにするサンプル
とはいっても株価のだけど
investpyで世界の株価データを取得してみた

で日立製作所の株価データをグラフにするのがあったので実線

stock = '6501' # Hitachi Ltd
country = 'japan'

stock_df = investpy.get_stock_recent_data(stock=stock, country=country)
stock_df.reset_index(drop=False, inplace=True)
stock_df.head()

ででる

reset_index() のオプションについて調べてみた
Pandas.DataFrameのインデックスをreset_indexメソッドで振り直す

によれば
DataFrameのreset_indexメソッドを使えば、DataFrameの行のindexを簡単に振り直すことができる

ということ

drop=False
については
オリジナルのindexを列として保存しておくならFalse、保存しないならTrue

inplace=True
については
reset_indexを実行したオブジェクト自体を変更する場合はTrue、変更しないのならFalse

つまり reset_index() でインデックス番号が振られるので
head() などで絞り込みができる

あとはグラフにしてみる

from matplotlib import pyplot as plt
import matplotlib.dates as mdates
import seaborn as sns; sns.set()


fig,ax = plt.subplots(figsize=(12,4))
locator = mdates.DayLocator()
formatter = mdates.ConciseDateFormatter(locator)
ax.xaxis.set_minor_locator(locator)
ax.xaxis.set_major_formatter(formatter)

sns.lineplot(data=stock_df, x='Date', y='Close')
ax.set_title('Hitachi Ltdt')
plt.show()

でできる

今度は経済指標に戻って
米国原油在庫量であるCrude Oil Inventories
が経済指標にあったので
event からこれを指定する

economic_data = investpy.economic_calendar(time_zone=None, time_filter='time_only', countries=['japan', 'united states'], from_date='01/01/2021', to_date='11/06/2021')
economic_data[economic_data['event']=='Crude Oil Inventories']

これで一覧で取得できた
あとは
actual
forecast
previous
の3つをグラフにして
対応する通貨の値動きを追加すれば
どんな値動きをしていたのかがわかる

次に新規失業保険申請件数
これは
Initial Jobless Claims
なので

economic_data[economic_data['event']=='Initial Jobless Claims']

となる

ただし
ISM Non-Manufacturing PMI (Jan)
というように月などが入っていると完全一致しないため
== では判定できない

python 文字列 含む 判定 pandas
で検索し
pandasで特定の文字列を含む行を抽出(完全一致、部分一致)

を参考に特定の文字列で始まるものを試す

str.contains(): 特定の文字列を含む
str.startswith(): 特定の文字列で始まる
があたりっぽい

print(df[df['name'].str.contains('li')])

がサンプル
なので

economic_data[economic_data['event'].str.contains('ISM Non-Manufacturing PMI')]

とすれば

ISM Non-Manufacturing PMI
を含むものを抽出することができるので
月ごとの結果が取得できるようになる

とりあえず取得するべき経済指標に関しては

economic_data2 = investpy.economic_calendar(time_zone=None, time_filter='time_only', countries=['japan', 'united states'], from_date='01/01/2021', to_date='31/01/2021')
economic_data2[economic_data2['importance']=='high']

で1月の重要経済指標を取得し表示

あとはグラフなどにしたい経済指標を絞り込む
英語なので google 翻訳などで調べていくと

ISM Manufacturing PMI
ISM製造業PMI

ADP Nonfarm Employment Change
ADP非農業部門雇用者数

Crude Oil Inventories
米国 原油在庫量

新規失業保険申請件数
これは
Initial Jobless Claims

ISM非製造業指数
ISM Non-Manufacturing PMI

Nonfarm Payrolls
米非農業部門雇用者数

Unemployment Rate
失業率

JOLTs Job Openings
JOLTS求人労働異動調査
つまり求人情報の数

Core CPI
消費者物価指数
正式名称は生鮮食品除く総合指数。生鮮食品とは、生鮮魚介、生鮮野菜、生鮮果物のこと。

Core Retail Sales
米国コア小売売上高前月比

PPI
生産者物価指数
生産者が出荷した製品や原材料などの販売価格の変動を調査・算出した経済指標

Retail Sales
小売売上高
米国の小売・サービス業の月間売上高
インフレと経済活動を評価する

Building Permits
(Building Permits)は、政府や他の規制当局が発行した新施設の建設のための許可数
中期的に不動産市場を予測する

Philadelphia Fed Manufacturing Index
フィラデルフィア連銀製造業景況指数

Existing Home Sale
中古住宅販売件数

CB Consumer Confidence
米国 消費者信頼感指数

Core Durable Goods Orders
コア耐久財受注
報告月の前月と比較した米国耐久財製造業者が受注した受注額を反映します。耐久財とは家具、電気器具などで、3年以上もつことが予想

Fed Interest Rate Decision
FRB政策金利

GDP (QoQ) 
実質GDP

New Home Sales
新築住宅販売戸数

Pending Home Sales
住宅販売契約指数

が重要指標

なお調べるときに
actual が None のものを除外すると見やすいと思うが

economic_data2[economic_data2['actual']=='None']

pandasで複数条件のAND, OR, NOTから行を抽出(選択)

を参考にやったがダメ

Pandasで NaN (Null) の行だけ抽出

を参考に
isnull() で抽出可能になった

python では not は ~ でなり
複数条件にするときには () で条件を囲む

今回
importance==hight
actual が isnull() でないもの
のものを表示するので

economic_data2[~(economic_data2['actual'].isnull()) & (economic_data2['importance']=='high')]

とすればOK

とりあえず経済指標の絞り込みはできるようになったので
次にグラフにする

複数のグラフを表示するには
altair でできたのでこれをつかう

経済指標カレンダーの取得

経済指標カレンダーの取得

FXで重要な経済指標をWebスクレイピングで取得する方法

を参考にみんかぶからスクレイピング

でーたを綺麗にするために
列名を主導で追加
必要の無い列、行を削除

が必要になる

しかし

import pandas as pd

url = 'https://fx.minkabu.jp/indicators' #みんかぶFXの経済指標URLを取得
dfs = pd.read_html(url) #テーブルのオブジェクトを生成

を実行してもリストになってしまう

Pandasで超簡単!WEBスクレイピング(表・htmlのtable取得)

を参考に
read?html に
必要なライブラリ不足かと思い

pip install beautifulsoup4 lxml html5lib

でインストールしてみたが変わらない

BeautifulSoupでテーブルスクレイピング

を参考に

import pandas as pd
url2 = 'https://en.wikipedia.org/wiki/Transistor_count'# 対象のwebページのurl
dfs = pd.read_html(url2)# webページに複数のテーブルがある場合、リスト形式でdfsに格納されます

とすると
webページに複数のテーブルがあるとリストになってしまう

なので

import pandas as pd

url = 'https://fx.minkabu.jp/indicators' #みんかぶFXの経済指標URLを取得
dfs = pd.read_html(url) #テーブルのオブジェクトを生成
dfs[0]

とすればテーブルとして表示できる

よくみたら出力するときに
dfs[0]
で指定していた….

とりあえずこれで当日の経済指標カレンダーは取得できそう

0からカウントされるので
0〜4までで1週間のカレンダー取得ができる

なお変動の pips については
米ドル/円やクロス円(ユーロ/円、ポンド/円など)の場合
1pip=0.01円(1銭)
10 pips=0.1円(10銭)
100 pips=1円(100銭)

米ドルストレート(ユーロ/ドル、ポンド/ドルなど)の場合
1pip=0.0001ドル(0.01セント)
10pip=0.001ドル(0.1セント)
100pip=0.01ドル(1セント)
となっている

これで
streamlit で表示できれば次にループ表示すれば週間カレンダーが表示できる
ので

mkdir fx_tool


作業ディレクトリを作成

使用するエディタは VS Code

cd fx_tool/
code ./

で作業ディレクトリに移動
vscode が起動する

main.py
を作成

久しぶりなのでほぼ忘れているので
Visual Studio Code キーボード ショートカット

をみながら操作

しかし途中でライブラリインストール済みでも import でエラー

このため
vscide import
で検索
VSCode で Python の import や from のエラーが消えない

を参考に

F1 を押す
Python: Select Interpreter を入力

使用する python を conda のものに設定

デフォルトの
Use default Python interpreter path
だとなぜか pandas のインポートができなかったけど
これで解決

from bs4 import BeautifulSoup
import pandas as pd
import streamlit as st

でライブラリインポート

アプリのタイトルは

st.title() 

で追加

経済指標カレンダーは
サイドバーで表示したいので

st.sidebar.write()

で記述していく

st.title('FX tool')

st.sidebar.write("""
# 経済指標カレンダー
今週の経済指標カレンダー
""")

url = 'https://fx.minkabu.jp/indicators' #みんかぶFXの経済指標URLを取得
dfs = pd.read_html(url) #テーブルのオブジェクトを生成
dfs[0]

dfs1 = dfs[0].dropna(subset = [4]) #4番にNaNが入っている行はバグなので、削除
dfs2 = dfs1.drop(2,axis =1) #2番目の列を削除。axis = 1は列を削除するオプション
dfs2.columns = ["発表時間", "経済指標", "前回変動幅(USD/JPY)","前回","予想","結果"]#列名を手動で追加。

#前処理終了

dfs2

st.sidebar.table(dfs2)
としてみたが
サイドバー表示だと見えにくいので本体の方にテーブル表示にする

なおサイドバーのwidth を変更する方法として
Change width of sidebar

にあるように
st.markdown
で設定も考えたが、使いにくいものになりそうなので別のレイアウトにすることに

Text-to-Speech API

GCP の Text-to-Speech API を使って
テキストから音声を生成する

入力したテキストを
音声を男性か女性か選択して
生成する

音声の文字起こしなら
Speech toText
のほうになる

GCP へログインし
認証情報 > API とサービスの有効化

Cloud Text-toSpeech API
をクリック

これには無料枠があるようでhttps://cloud.google.com/text-to-speech/pricing/?hl=JA
に記載されている

1ヶ月あたり
0〜100 万文字

音声合成マークアップ言語(SSML)タグも文字数カウントに含まれる

有効化のときに課金設定があるので注意

有効化できたら
認証情報で
認証情報を作成

サービスアカウントを作成する

続行
で完了
をクリック

これでサービスアカウントが作成される

このアドレスをクリックし
キーをクリック

鍵を追加

新しい鍵を追加
でタイプをJSONにする

これでJSONファイルをダウンロードしたら
環境変数を設定する

GOOGLE_APPLICATION_CREDENTIALS
を設定する

これにパスを設定する
ダウンロードしたJSONファイルを
secret.json に名前を変えておく

ダウンロードしたファイルを新しい順にするなら

lsコマンドでファイルを新しい順番、古い順番にソートする方法

を参考に

ls -lt

で表示されるので

cp raspberryPi-b787a5abd4d5.json secret.json

でコピーし

mv secret.json ~/notebook/


jupyter notebook で扱えるようにしておく

次に
notebook でos ライブラリをインポートすることで使っていく

import os
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'secret.json'

でOK

次にライブラリのインストール

Text-to-Speech クライアント ライブラリ

を参考に

pip install --upgrade google-cloud-texttospeech

をいれる

notebook でやるなら

!pip install --upgrade google-cloud-texttospeech

とする

これで準備できたので
音声の再生

from google.cloud import texttospeech

client = texttospeech.TextToSpeechClient()

synthesis_input = texttospeech.SynthesisInput(text="Hello, World!")

voice = texttospeech.VoiceSelectionParams(
    language_code="en-US", ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL
)

audio_config = texttospeech.AudioConfig(
    audio_encoding=texttospeech.AudioEncoding.MP3
)

response = client.synthesize_speech(
    input=synthesis_input, voice=voice, audio_config=audio_config
)

with open("output.mp3", "wb") as out:
    out.write(response.audio_content)
    print('Audio content written to file "output.mp3"')

クライアント ライブラリの使用

からコピペして
コメント部分を削除

client = texttospeech.TextToSpeechClient()

の部分で認証をしている

synthesis_input = texttospeech.SynthesisInput(text="Hello, World!")


出力する音声をセット
今回なら
Hello, World
となる

voice = texttospeech.VoiceSelectionParams(
    language_code="en-US", ssml_gender=texttospeech.SsmlVoiceGender.NEUTRAL
)

で声の設定
language_code で言語の指定
en-US なら英語

ssml_gender は性別の設定
NEUTRAL だとどっちでもないような音声になる

audio_config = texttospeech.AudioConfig(
    audio_encoding=texttospeech.AudioEncoding.MP3
)

で音声形式の指定
今回は MP3 にしている

これらのパラメータを

response = client.synthesize_speech(
    input=synthesis_input, voice=voice, audio_config=audio_config
)

でセットして音声を作成する

filename ="output.mp3"
with open(filename, "wb") as out:
    out.write(response.audio_content)
    print(f'Audio content written to file {filename}')

と最後を変えることで音声ファイル名を簡単に変更できる

wb なので
バイナリ形式で書き込み

しかし Cloud SDK がないと実行できないみたいなので
Google Cloud SDK のインストール

を参考に

echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list


Cloud SDK の配布 URI をパッケージ ソースとして追加

sudo apt-get install apt-transport-https ca-certificates gnupg


apt-transport-https がインストールされているのを確認

curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -


公開鍵のインポート

sudo apt-get update
sudo apt-get install google-cloud-sdk


リポジトリ更新と
google-cloud-sdk のインストール

しかしマニュアルを読んでみたら
全機能は使えないので
Linux 用インストールでないとダメと気づいた
Ubuntu 18.04 (WSL) に、Google Cloud SDK をインストールする

も参考に

一度

sudo apt-get remove google-cloud-sdk
sudo apt remove python3-crcmod 

で削除

curl -O https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-337.0.0-linux-x86_64.tar.gz

でファイルを取得

tar zxvf google-cloud-sdk-337.0.0-linux-x86_64.tar.gz 


圧縮ファイルを展開

/google-cloud-sdk/install.sh

を実行し
Google Cloud SDK のパスを通すことでコマンド補完ができるようになる

source .bashrc

を実行して設定反映を忘れずに

./google-cloud-sdk/bin/gcloud init


SDK初期化と認証開始

You must log in to continue. Would you like to log in (Y/n)?  

となるので
Y
とすると
ブラウザが立ち上がり
認証画面になる

認証成功なら
https://cloud.google.com/sdk/auth_success
の画面がでる

次にどのプロジェクトをデフォルトにするか聞かれる

Please enter numeric choice or text value (must exactly match list 
item):  
Please enter a value between 1 and 12, or a value present in the list: 

となるので
任意のプロジェクト No を入力すると終了

gcloud components update

でコンポーネントを更新

しかしこれでもダメ

GCPの Text-to-Speech で 文字読み上げ を作る

を参考に

pip install pydub


MP3再生に必要なパッケージをいれる

pip install google-cloud-storage

をしたけどダメ

もう一回APIの確認をしたら
Cloud Speech Text API が無効になっていたので
再度有効化してから
もう一度鍵ファイルを作成することで有効化された

これで再度実行したら無事に音声が作成された

ubuntu 16 へ streamlit インストール

ubuntu 16 へ streamlit インストール

【Streamlit】インストールしてみた

を参考に

pip install streamlit

でインストール

streamlit hello

でデモのサンプルを起動できる

  If you're one of our development partners or you're interested in getting
  personal technical support or Streamlit updates, please enter your email
  address below. Otherwise, you may leave the field blank.

とでるけど気にせずに
Enter

これでブラウザで webアプリが起動する

jupyter notebook の結果をHTMLにする

jupyter notebook の結果をHTMLにする

jupyter-notebook --generate-config

で設定ファイルを作成

すでに存在するなら

Overwrite /home/snowpool/.jupyter/jupyter_notebook_config.py with default config? [y/N]N

というように確認されるので
この場合はN で Enter すればOK

vim ~/.jupyter/jupyter_notebook_config.py 

でファイルを開き

最終行に

import os
from subprocess import check_call

c = get_config()

def post_save(model, os_path, contents_manager):
    """post-save hook for converting notebooks to .py and .html files."""
    if model['type'] != 'notebook':
        return # only do this for notebooks
    d, fname = os.path.split(os_path)
    check_call(['ipython', 'nbconvert', '--to', 'script', fname], cwd=d)
    check_call(['ipython', 'nbconvert', '--to', 'html', fname], cwd=d)

c.FileContentsManager.post_save_hook = post_save

を追記し保存

jupyter-notebook 

で起動し

保存アイコンをクリックすると
jupyter notebook の ipynb ファイル保存時に
HTMLが作成される

ubuntu VLC が落ちるときの対処

ubuntu VLC が落ちるときの対処

ubuntu16.04 で動画から静止画切り出し
で以前静止画の取り出しをしたので
今回も行おうとしたが
VLC を起動し動画を再生しようとしても
落ちてしまう

VLC で動画再生に問題

を参考に

ツール > 設定

ビデオの出力を自動から
X11ビデオ出力(XCB)
にすることで解決

Word2Vec

Word2Vec

テキスト解析して学習して
単語の意味をベクトル表現する方法

モデルは隠れ層と出力層の2層ニューラルネットワークになっている

Word2Vec を使うことで
ある単語や文章と似通った単語や文章を解析できる


コーパスにある単語の得微量ベクトルを学習し出力する

python で Word2Vec を使うには
gensim ライブラリをインストールする

pip3 install gensim

Mecab でコーパスを作成する

Word2Vec で類似語解析するには
テキストデータから
コーパス(基礎資料)を作成する必要がある

今回は明治以降の文学者15人のデータを wiki から取得し学習

まずはライブラリインストール

import MeCab
import requests

from bs4 import BeautifulSoup

次にターゲットURL指定

domain ="https://ja.wikipedia.org/wiki/"

次に対象人物をリストで宣言

names =["森鴎外","夏目漱石","島崎藤村","与謝野晶子","坪内逍遥","石川啄木",
        "谷崎潤一郎","芥川龍之介","萩原朔太郎","川端康成","志賀直哉","中原中也",
        "太宰治","大岡昇平","三島由紀夫"]

次に Mecab を分かち書きモードでインスタンス生成
コーパス(基礎資料)をいれるリストの宣言

m=MeCab.Tagger("-Owakati")
corpus =[]

ループ処理で
URL+キーワード
で項目のHTMLを取得

for name in names:               
    with requests.get(domain + name) as response:
        soup = BeautifulSoup(response.content, "html.parser")
        p_text = soup.find_all("p")
        for p in p_text:         
            corpus.append(m.parse(p.text).strip())

最後にコーパス(基礎資料)の結果を
data.txt に出力

with open("data.txt","w") as file:                      
    file.write("\n".join(corpus))

全体ソースは

import MeCab
import requests
from bs4 import BeautifulSoup

domain="https://ja.wikipedia.org/wiki/"

names =["森鴎外","夏目漱石","島崎藤村","与謝野晶子","坪内逍遥","石川啄木",
        "谷崎潤一郎","芥川龍之介","萩原朔太郎","川端康成","志賀直哉","中原中也",
        "太宰治","大岡昇平","三島由紀夫"]

m=MeCab.Tagger("-Owakati")
corpus =[]

for name in names:
    with requests.get(domain + name) as response:
        soup = BeautifulSoup(response.content, "html.parser")
        p_text = soup.find_all("p")
        for p in p_text:
            corpus.append(m.parse(p.text).strip())

with open("data.txt","w") as file:
    file.write("\n".join(corpus))

となり
実行すると
data.txt が作成される

次に
data.txt を解析し学習モデルを生成

gensim から Word2Vec をインポート

from gensim.models import word2vec

次にファイルからコーパス(基礎資料)の読み込み

corpus = file.read().splitlines()

splitlines() を使うと改行コードをリストにするときに入れなくなる
python でファイルを read してリストにする時に、改行コードを入れない
https://qiita.com/suzuki-hoge/items/8eac60f7b68044eea6c1
を参考に

次にコーパス(基礎資料)を元に学習モデルを生成

corpus =[sentence.split() for sentence in corpus]
model = word2vec.Word2Vec(corpus,size=200,min_count=20,window=10)

次にモデルを元に似通ったキーワードをsy筒力

今回は文学と似通ったキーワードを出力

similar_words = model.wv.most_similar(positive=["文学"], topn=9)
print(*[" ".join([v ,str("{:.2f}".format(s))]) for v, s in similar_words], sep="\n")

全体ソースは

from gensim.models import word2vec

file = open("data.txt")
corpus = file.read().splitlines()

corpus =[sentence.split() for sentence in corpus]
model = word2vec.Word2Vec(corpus,size=200,min_count=20,window=10)

similar_words = model.wv.most_similar(positive=["文学"], topn=9)
print(*[" ".join([v ,str("{:.2f}".format(s))]) for v, s in similar_words], sep="\n")

結果は

物語 0.99
作 0.98
題材 0.98
代表 0.98
時代 0.97
評論 0.97
世界 0.97
描い 0.97
歌 0.96

となった

参考書籍とは違ったけど
年数が立っているので誤差範囲

print(*[" ".join([v ,str("{:.2f}".format(s))]) for v, s in similar_words], sep="\n")

がわかりにくいので調べてみた

python {:.2f}
で検索したら
{インデックス番号:書式指定}
ということで

意味は下2桁で小数点タイプということ

これは format() の使い方であるということ

Pythonの文字列フォーマット(formatメソッドの使い方)

をみることで解決

なお今回のようにコーパス(基礎資料)作成
モデル構築
類似度の集計まで一気にやらず
モデル構築時点で一度ファイルに出力すれば
計算処理時間が縮小できる

model.save("data.model")

全体ソースは

from gensim.models import word2vec

file = open("data.txt")
corpus = file.read().splitlines()

corpus =[sentence.split() for sentence in corpus]
model = word2vec.Word2Vec(corpus,size=200,min_count=20,window=10)
model.save("data.model")

similar_words = model.wv.most_similar(positive=["文学"], topn=9)
print(*[" ".join([v ,str("{:.2f}".format(s))]) for v, s in similar_words], sep="\n")

として実行すると
data.model が作成される

あとは学習済みモデルを読み込むには

model.word2vec.Word2Vec.load("data.model")

でOKらしいので

word2vecmodel_data.py
を作成し

from gensim.models import word2vec

model =word2vec.Word2Vec.load("data.model")

similar_words = model.wv.most_similar(positive=["文学"], topn=9)
print(*[" ".join([v ,str("{:.2f}".format(s))]) for v, s in similar_words], sep="\n")

で実行したら

物語 0.99
歌 0.99
古典 0.99
海 0.98
時代 0.98
近代 0.98
作 0.98
世界 0.97
歴史 0.97

と同じ結果になった

Word2Vecの学習済み日本語モデルを読み込んで使う
を参考に

参考書籍は

なお kindle Fire でみるときには
拡大しなくても見れるので
10インチがおすすめ

カバーがほしい場合には
マグネット機能で閉じたらOFFにしてくれる純正がおすすめ