ビジネスパーソン・ガジェット置場 empty lot for business

営業や仕事、それに伴う生活を便利に楽にするツール、ガジェットを作ります。既にあるツールも自分用にカスタマイズ。

たばこ本数可視化アプリ【python+streamlit】

日々吸っているたばこの本数を管理し、そこから日々のコストを算出。また、週及び月のコスト予測を算出。それらを1画面で管理、可視化しているガジェットです。電子タバコと紙巻きたばこ併用に対応可能で、それぞれのたばこの値段、紙巻きと電子の比率をスライダーで設定できます。

f:id:kslabo51:20220327190049j:plain

例えばこんな状況で

今回のガジェットは、こういう声に対応
「タバコも高くなってきたし、日々吸っている本数を管理して、月に一体どれくらいの費用がかかるのか把握したい。電子タバコも普及してきたので、併用なんだけど、それぞれ値段も違うからいざ、費用予測を計算しようとすると面倒なんだよな。」

f:id:kslabo51:20220327190205p:plain

このガジェットでできることはこちら

  • タバコを吸った時間を表テーブルで確認できます。
  • 1日の本数の比較、またその本数を費用に落とした場合の1日のコストをグラフで確認できます。
  • たばこの値段はだんだん変化していますが、自分のたばこの値段を設定できます。
  • 電子と紙巻き併用をしている場合でもその比率を設定できます。
  • これから1ヶ月のコスト予測を出します。

注意点はこちら

現在の設定ではたばこの値段を変えるとグラフ上のコストも全て変わってしまいます。(ただし、1ヶ月のコスト予測は新しいもので反映します)

 

評価(自己)

役立ち度  ★★★★(良し)
効率化   ★★★(平均)
ミス防止  ★★★(平均)
楽しさ   ★★★★(良し)
操作性   ★★★★(良し)

 

実行環境    

使用環境    streamlit
使用言語    Python
使用ライブラリ pandas、 gspread、oauth2client.service_account、altair、

        math、streamlit

コード

import pandas as pd
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import altair as alt
import math
import streamlit as st

st.title('たばこ本数可視化アプリ')

def get_worksheet():
    SP_CREDENTIAL_FILE = 'secret.json'

    # APIを使用する範囲
    SP_SCOPE = [
        'https://spreadsheets.google.com/feeds',
        'https://www.googleapis.com/auth/drive'
    ]

    # 今回使用するスプレッドシートのurlのdの直後
    SP_SHEET_KEY = 'スプレッドシートのI D'
    SP_SHEET = 'シート名'

    # 認証情報を組み合わせ認証する
    credentials = ServiceAccountCredentials.from_json_keyfile_name(SP_CREDENTIAL_FILE, SP_SCOPE)
    gc = gspread.authorize(credentials)

    # スプレッドシートの情報を取ってくる
    sh = gc.open_by_key(SP_SHEET_KEY)
    worksheet = sh.worksheet(SP_SHEET)
    return worksheet

def get_chart(kamimaki, denshi, month, week, kami_rate):
    worksheet = get_worksheet()
    
    data = worksheet.get_all_values()
    df = pd.DataFrame(data[1:], columns=data[0])
    daily_num = {}
    for day in df.columns:
        num = len(df[day][df[day]!=''])
        if num != 0:
            daily_num[day] = num
    agg = pd.DataFrame(daily_num, index=['本数'])
    agg = agg.T.reset_index()
    agg = agg.rename(columns={'index': 'Date'})
    daily_prices = []
    for i in range(agg.shape[0]):
        d_price = math.floor(agg.iloc[i, 1] * (1-kami_rate/10)) * denshi
        k_price = math.ceil(agg.iloc[i, 1] * kami_rate/10) * kamimaki
        daily_price = d_price + k_price
        daily_prices.append(daily_price)
    agg['費用'] = daily_prices
    
    ymin1 = 0
    ymax1 = 20
    ymin2 = agg['費用'].min() - 10
    ymax2 = agg['費用'].max() + 10
    base = alt.Chart(agg).encode(
        alt.X('Date:T', axis=alt.Axis(title=None))
    )

    line1 = base.mark_line(opacity=0.3, color='#57A44C').encode(
        alt.Y('本数',
              axis=alt.Axis(title='本数', titleColor='#57A44C'),
              scale=alt.Scale(domain=[ymin1, ymax1])
             )
    )

    line2 = base.mark_line(stroke='#5276A7', interpolate='monotone').encode(
        alt.Y('費用',
              axis=alt.Axis(title='費用', titleColor='#5276A7'),
              scale=alt.Scale(domain=[ymin2, ymax2])
             )
    )
    chart = alt.layer(line1, line2).resolve_scale(
        y = 'independent'
    )
    monthly_cost = agg['費用'].values.mean()*month
    weekly_cost = agg['費用'].values.mean()*week
    return chart, monthly_cost, weekly_cost



st.sidebar.write('### 紙巻きたばこ値段')
kami = st.sidebar.slider(label='紙巻きたばこ',min_value=400,max_value=600, value=430)
st.sidebar.write('### 電子たばこ値段')
den = st.sidebar.slider(label='電子たばこ',min_value=400,max_value=600, value=430)

st.sidebar.write('### 紙巻き:電子比率')
kami_rate = st.sidebar.slider(label='紙巻きの割合',min_value=0,max_value=10, value=6)

kamimaki = kami / 20
denshi = den / 20
week = 7
month = 30
chart, monthly_cost, weekly_cost = get_chart(kamimaki, denshi, month, week, kami_rate)

st.sidebar.write('### 月額費用')
st.sidebar.write(f'#### {int(monthly_cost)}円')

st.sidebar.write('### 週間費用')
st.sidebar.write(f'#### {int(weekly_cost)}円')

st.write('### 喫煙時間一覧表')

worksheet = get_worksheet()
data = worksheet.get_all_values()
df = pd.DataFrame(data[1:], columns=data[0])
st.dataframe(df)

st.write('### 喫煙本数&費用グラフ')
st.altair_chart(chart, use_container_width=True)