よしたく blog

ほぼ週刊で記事を書いています

Python製のWebフレームワークStreamlitをさわってみた

datatech-jp Casual Talks #1に参加したときに知った、Python製のWebフレームワークStreamlitを触ってみた。

yoshitaku-jp.hatenablog.com

streamlit.io

github.com

Streamlitのサイトを覗くとまずThe fastest way to build and share data appsと書いてあり、データ周りで共有を楽にすることを全面に打ち出していることがわかる。 Pythonスクリプトで実行できるので、データ分析スクリプトの内容をそのまま流用できるのも嬉しいし、Pythonで完結されるのでフロントエンドの知識が不要な点も大きい!

今回はどれぐらい簡単に表示できるのか試してみる。 まずはDockerを使って環境の準備から立ち上げ実施し、次にseabornのtitanicデータを使って可視化をおこなう。

準備

streamlitフォルダを作成し、直下にDockerfileとdocker-compose.ymlを用意する。streamlit以外にもライブラリが入っているけど立ち上げ後に使うので、必要なければ入れなくても大丈夫🙏

Dockerfile

FROM python:3.9.10

RUN pip install streamlit
RUN pip install pandas
RUN pip install seaborn
RUN pip install matplotlib

docker-compose.yml

version: '3'
services:
  app:
    build: .
    container_name: 'streamlit'
    command: "streamlit run src/app.py"
    ports:
      - "8501:8501"
    volumes:
      - "./src:/src/"

次にstreamlit配下にsrcフォルダを用意し、app.pyを作成する。app.pyには次の内容を記述する。

import streamlit as st

# タイトル
st.title("Streamlit Application - titanic data")

立ち上げ

ここまで用意できたらdocker-compose up -d --buildで起動し、http://localhost:8501/にアクセスする。次の画面が表示される。 まずは立ち上げまで実施してみた。

f:id:yoshitaku_jp:20220220200240p:plain

データ周りを表示してみる

app.pyの内容を次のように変更してみる。 スクリプトのコメントにも書いたけど、seabornのサンプルデータtitanicを元に、生存者データの可視化とチケット別生存者データの可視化で2つの図を表示してみた!

import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import streamlit as st

# タイトル
st.title("Streamlit Application - titanic data")

# タイタニックデータの読み込み
titanic = sns.load_dataset("titanic")

# 生存者データの可視化
st.subheader("Number of Titanic Survivors")

fig1 = plt.figure(figsize=(10, 4))
sns.countplot(x="survived", data=titanic)
st.pyplot(fig1)

# チケット別生存者データの可視化
st.subheader("Number of Titanic Survivors by Ticket")

fig2 = plt.figure(figsize=(10, 4))
sns.countplot(x="survived", hue="class", data=titanic)
st.pyplot(fig2)

このコードは次のように表示してくれる。 無事に2つの図が表示されている💡

f:id:yoshitaku_jp:20220220201133p:plain

まとめ

ダッシュボード周りはコード化しづらく、現在もダッシュボードの変更履歴が管理できない部分は頭を悩ませていて、今後広く問題になると思っていたのでStreamlitのようなものが解決の糸口になってくれると嬉しいと感じた。 他に似たようなdashもあるので、こちらはこちらも触って比較したい💪

github.com

datatech-jp Casual Talks #1 に参加した!

datatech-jpのCasual Talks #1 が開催されるとのことで覗いてみた!

datatech-jp.connpass.com

発表内容

資料待ち / syou6162

会社のテックブログに掲載されるとのことで公開待ち🙏

公開されていたので貼りました🙏

tech-blog.monotaro.com

小さく始めるデータ基盤 / reizist

speakerdeck.com

スタートアップ企業でデータ基盤を作成した話だった。 どんなデータを、どこに、どうやって集めるのかと言った定義から、実際に選択された製品までまとまっていてわかりやすかった。 コストのところではCloudRunとBigQueryで200円ということで、コンビニコーヒー2杯と考えたらめっちゃ安い! なかなか公開できない部分ではあるけど、スタートアップ以外ではどのぐらいのコスト感で運用しているのか気になった🙏

BigQueryのネイティブJSON型がサポートされたので触ってみた / ohsawa0515

speakerdeck.com

BigQueryのネイティブJSON型を触ってみた話だった。 今までSQLやユーザ定義関数を使ってスキーマ定義していたものがJSON型で触りやすくなったのはいい話だと思った。 8スライドめにパフォーマンスについても言及されていて素晴らしいと思った。 テーブルサイズがString型よりも半分近くも削減されるのは、理由が気になる!

開発者生産性指標の可視化 / udzura

speakerdeck.com

For Keysというソフトウェア開発チームのパフォーマンスを示す4つの指標を、自チームでどう実現したかという話だった。 エンジニアとしてのパフォーマンスを可視化できるなんて面白い! また、それをどうやって集めていったかの話にも言及されていて勉強になった。

もう一つの話題で面白かったのがDashboard as Codeだった。 ダッシュボードの変更履歴や構成が管理できない部分は、今後自分も問題になるんじゃないかと思っていて、ここにチャレンジしているのはすごいと思った。 StreamlitというPython製のWebフレームワークが紹介されていて、ノートブック系で試行錯誤した結果をPandasやNumPyそのままの形でダッシュボードまで持っていきやすい点がいいと思った。 時間があったら触ってみたい!

まとめでは、Four Keysの他にも有効な指標がないか模索している点や、ダッシュボードが活用されているかも追っていくことが明言されていて、今後も気になる!

まとめ

datatech-jpのCasual Talks #1に参加し、聞けた範囲でメモを残した!

  • 小さい規模でのデータ基盤について
  • 技術的に検証した話
  • 指標を設定してそれをどう追っていったかとダッシュボードの変更管理

と話題が重ならず、そしてどれも興味深く話を聞くことが出来た!

datatech-jpのSlackでは書籍の輪読会なども実施されていて見ていて楽しい! 勉強会中はチャンネルでコミュニケーションが盛り上がっていたが、Twitterハッシュタグでも盛り上がっている様子が伝わればいいなと思った! 2回目があれば楽しみにしています!!

Azure Data FactoryのFailアクティビティについて調べた

f:id:yoshitaku_jp:20220206100004p:plain

2021年後半にAzure Data FactoryのFailアクティビティが追加されました。10月頃にプレビューで登場していたのは確認していたのですが、いつのまにかGAされていました。Failアクティビティは名前の通りパイプライン上で意図的にエラーを引き起こしたいときに使えるものです。

docs.microsoft.com

Failアクティビティが登場するまでは、パイプライン上でゼロ除算を実行させたり、Web アクティビティで存在しないURLにアクセスしてエラーを引き起こし処理を止めていました。あまり良い処理の止め方ではないのでFailアクティビティが登場してよかったです。ここでは実際にどう動くのかをまとめました。なお、日本語では失敗アクティビティという名前がついていますが今回はFailアクティビティに統一して記事を書いています。

Failアクティビティ作成

2022年02月現在、Failアクティビティは全般カテゴリの中にあります。

f:id:yoshitaku_jp:20220206085435p:plain

実際に配置してみると以下のようになります。真ん中にあるのがFailアクティビティです。左右にはWaitアクティビティを置いています。

f:id:yoshitaku_jp:20220206090527p:plain

動きの確認

当たり前ですが、エラーが発生しFailアクティビティで処理が止まってくれないと意味がありません。さきほどのパイプラインをデバッグ実行してみます。

実行結果を見ると後続のFailアクティビティが実行されておらず、無事に処理が止まっていることが確認できます。

f:id:yoshitaku_jp:20220206091156p:plain

次はトリガー実行しメールが送信されるかも確認します。アラート設定は省きますが、こちらも無事に送信されていました。

f:id:yoshitaku_jp:20220206094120p:plain

注意点

注意点としてはForEachアクティビティなどのループ処理の中でFailアクティビティでエラーを引き起こしても、ループ処理は継続され抜け出さないことには注意が必要です。

Cloud Storageでオブジェクトのライフサイクルを設定する

多くの企業がデータ分析基盤を選択するときにGoogle Cloud Platformを選んでいる気がするので、気になって少し触ってみた。 わからないことが多すぎてオープンワールドのゲームに飛び込んだような感覚なので、まずは手軽にCloud Storageでライフサイクルの設定をおこない記事にした🙏

ライフサイクルの設定

バケットsandbox-yoshitakuを作成した状態になっている。今回はこのバケットで設定をおこなってみる。 対象のバケットをクリックする。

f:id:yoshitaku_jp:20220130164928p:plain

バケットの詳細に移動してくる。タブがいくつかあるなか、ライフサイクルがあるのでクリックする。 現時点で並んでいるのは次の5つになる。

  • オブジェクト
  • 設定
  • 権限
  • 保護
  • ライフサイクル

権限保護ライフサイクルは設定タブの中にまとまりそうだけど、この3つだけ外に出されている点が気になった🙋

f:id:yoshitaku_jp:20220130165148p:plain

ライフサイクルのタブに移動すると、ルールの追加があるのでクリックする。

f:id:yoshitaku_jp:20220130165234p:plain

オブジェクト ライフサイクル ルールの追加に移動してくる。デフォルト設定で作成されたバケットはストレージクラスがStandardなので、Standardからどこへ移動させるかの設定をおこなう。

移動先のストレージクラスは3つから選べ、削除も入れると選択肢としては4つになる。 今回はデータレイクの選択肢として一番最初に使われそうなNearline(アクセスが 1 か月に 1 回未満のバックアップとデータに最適)を選択する。

  • Nearline
  • Coldline
  • Archive
  • 削除

f:id:yoshitaku_jp:20220130165303p:plain

オブジェクト条件の選択に移動してきて、どの条件のオブジェクトを先ほど設定したNearlineに移動させるかを設定していく。 データ分析基盤だと、データが届いて1ヶ月ぐらいで移動させるケースが多いので、年齢に30を設定する。 最後に作成をクリックして完了となる。

f:id:yoshitaku_jp:20220130165359p:plain

作成した設定がライフサイクルのタブに表示されていればOKとなる👌

ゴミ箱マークをクリックすれば設定の削除できるが、今の時点で確認ダイアログは出なかったので注意が必要😕 細かい設定をした後に間違えて消してしまうなんてことがないようにしたい。 確認ダイアログ求む〜🙏

f:id:yoshitaku_jp:20220130165443p:plain

まとめ

Cloud Storageでオブジェクトのライフサイクルを設定してみた。

オブジェクト ライフサイクル ルールの追加での、年齢選択肢はデータが生成されてということを表現していると思っているけど、表現としてはわかりづらくて戸惑った🙁 他の選択肢は割とわかりやすい表現になっており、英語でageと表現されていて翻訳したのかなぁと思った。

画面全体で言えば、移動先を選択した画面のアクションを選択にチェックマーク✅がついており、現在の設定段階が縦で表現されているのが、個人的に見慣れないなぁと思った👀

ちなみに、恥ずかしながらNearlineという表現に初めて出会った🙇 参考にリンクを張っておく🙏

ニアラインストレージ (nearline storage)とは | 「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典

PyArrowでCSVをParquetに変換する

今回は PyArrow を使って CSV を Parquet に変換してみた。

データレイクは生データを溜めることが主目的だが、レイクハウス型のアーキテクチャの流れもあり、データを利用したいサービス側が利用しやすいような整形化されたデータを用意する用途も増えてくると思う。 そうなると CSV ファイルでデータを持つよりかは Parquet で持つほうが、利便性が高いので、今後はこの変換業務も増えてくるように考えている。

今回は Pandas で CSV ファイルを読み込み、PyArrow を使って Parquet ファイルに出力する。 PyArrow から CSV ファイルを読み込んで Parquet ファイルに出力する方法もあるが、ファイル出力前に Pandas を使ってデータを整形するケースが多いと考え、こちらで試した。

インストール

まずはライブラリをインストールする。 pandas で CSV ファイルを読み込むため、pandas もインストールする。

pip install pyarrow pandas

コード

全体像

読み込んで出力するだけなのでシンプルなものになった。 ファイル形式を変更するだけでサイズが削減されるメリットは有るが、実務では欠損値を補ったりデータの整形が入るのでもっと長くなる。

import pandas as pd

import pyarrow as pa
import pyarrow.parquet as pq

df = pd.read_csv("./test.csv")

table = pa.Table.from_pandas(df)

pq.write_table(table, "./test.parquet")

まずは Pandas を使って CSV を読み込み、DataFrame に変換する。

df = pd.read_csv("./test.csv")

PyArrow のTable.from_pandasメソッドを使って、pandas.DataFrame から Arrow Table と呼ばれる形式に変換する。

table = pa.Table.from_pandas(df)

最後にwrite_tableメソッドで Arrow Table で持っているデータを Parquet ファイルに出力する。

pq.write_table(table, "./test.parquet")

ステップとしてはこれだけで CSV ファイルから Parquet ファイルに変換ができてしまう。とても簡単でびっくりした。

データ量の削減

Parquet ファイルは列指向でデータを持ち、同じデータが圧縮されるのでファイルサイズが減っていた。 しかし、このあたりはデータの中身によるのですべてのファイルが半分以下になるわけではないので気をつけたい。 改めて、ファイルの形式だけでなく、データの中身まで目を配っていかなければいけないなという感想を持った。

f:id:yoshitaku_jp:20220123174609p:plain

余談だが、最初はローカル環境で生成した 1GB の CSV ファイルを Parquet ファイルにしようとしたとき、数キロバイトまで圧縮されていた。 流石に圧縮されすぎているので、これはうまくいっていないケースだと思う。 結果的に大きいファイルを扱う際はプログラムを動かす環境などにも考慮が必要だと感じた。

Pythonでの再帰関数の上限を変更する

Python ではデフォルトで再帰関数の上限が 1000 に設定されている。知らなかった...

sys.getrecursionlimit()で現在の上限を確認できる。 今回はサッと確認するのに便利なGoogle Colaboratoryを使う。

import sys

print(sys.getrecursionlimit())

たしかに 1000 に設定されている。

1000

例えば次の再帰関数を実行するとRecursionError: maximum recursion depth exceeded in comparisonエラーが吐かれる。たしかに 1000 回以上には対応していないことがわかる。

def test(n):
  if n == 1:
    print('終わり')
    return
  test(n - 1)
test(1001)
RecursionError: maximum recursion depth exceeded in comparison

再帰関数の上限があることを確認したが、その上限値をsys.setrecursionlimit()関数で変更できる。

sys.setrecursionlimit(10000)

print(sys.getrecursionlimit())

最初に確認したときは 1000 だったが、変更後の 10000 に変更されている。

10000

再帰関数を再度実行すると無事に処理が終了していることがわかる。

def test(n):
  if n == 1:
    print('終わり')
    return
  test(n - 1)
test(1001)
終わり

Python 以外の言語でも再帰関数の上限が設定されているのか確認したが、明確な情報は出てこなかった。 この制限は Python 特有なのかもしれない。

Azure Data Factoryを使って、新規・変更済みファイルのみをデータレイク間でコピーする

Azure Data Factoryを使って、新規・変更済みファイルのみをデータレイク間でコピーする。新規・変更済みファイルのみを移動対象とすることで、無駄なデータ移動が発生せず、料金も抑えることができるようになる。

準備

パイプライン

パラメーターを2つ用意する。このパラメーターは、トリガーから値を受け取る際に必要になる。受け渡された値の期間にファイルの変更があった場合、変更対象となりファイルがコピーされる。今回は次の名称にした。

  • LastModified_From
  • LastModified_To

f:id:yoshitaku_jp:20220107172214p:plain

アクティビティ

コピーアクティビティを使用し、ソースの設定項目を変更する。シンク側は特に設定する必要はないので省略した。

ソース

ソースに値を設定する。

「ファイルパスの種類」と「再帰的に実行」は、データレイクのルートフォルダを指定し、そこから全てのファイルを調べたいため設定した。この部分は、プロジェクトによって設定を変更してほしい。 「最終変更日時でフィルター」でトリガーから与えられる期間をファイルの変更検知対象とし、この期間に変更があったファイルだけコピーされるようになる。

  • ファイルパスの種類
  • 最終変更日時でフィルター
    • 開始時刻
      • @{pipeline().parameters.LastModified_From}
    • 終了時刻
      • @{pipeline().parameters.LastModified_To}
  • 再帰的に実行
    • オン

f:id:yoshitaku_jp:20220107174358p:plain

トリガー

トリガーを作成し、作成したパイプラインに紐付ける設定をする。

トリガーの種類はTumblingWindowTriggerを選択する。タンブリング ウィンドウトリガーで使用できるシステム変数@trigger().outputs.windowStartTime@trigger().outputs.windowEndTimeをパイプラインのパラメーターに渡す設定をおこなう。これでトリガー実行されるたびに、パイプラインの開始時刻の@{pipeline().parameters.LastModified_From}とパイプラインの終了時刻の@{pipeline().parameters.LastModified_To}が動的に変更されるようになる。

f:id:yoshitaku_jp:20220107180710p:plain

繰り返しを15分に設定した。こうすると15分毎にトリガーが実行される。

  • 00:00~00:15
  • 00:00~00:30
  • 00:30~00:45
  • 00:45~01:00
  • 01:00~01:15
  • ...続く

今回のパイプラインとの動きと関連してみると、各15分間の間に変更があったファイルが変更対象となり、コピーが実施される。トリガーの間隔はデータの更新頻度や想定されるデータ量などプロジェクトにあった値を設定する。

実行

実際に動かしたところを見てみる。 ソース元となるsourceデータレイクの中身はルートディレクトリに1つのファイルが配置され、test_system_aディレクトリの中に2つファイルが配置されている。

f:id:yoshitaku_jp:20220109101211p:plain

f:id:yoshitaku_jp:20220109101152p:plain

実行すると、シンク先となるdestinationデータレイクの中身に、同じ構成かつ同じファイルが配置されている。

f:id:yoshitaku_jp:20220109101226p:plain

f:id:yoshitaku_jp:20220109101238p:plain

1つのファイルに変更があった場合はそのファイル単独で実行される。例えばtest_system_aディレクトリの中のtarget_a.txtだけ変更した場合は、そのファイルのみ最終更新日時が変わっていることがわかる。

f:id:yoshitaku_jp:20220109103608p:plain

f:id:yoshitaku_jp:20220109103624p:plain

注意点

記事のタイトルにもあるように、新規・変更済みファイルのみを対象とするので、ソース元からファイルが削除されても検知されない。これはファイルの更新日時を見てコピーするかしないかを判断しているためである。なので、データレイク間で完全同期を求める用途には適しておらず、そういった場合には料金とデータ量が増えてしまうが完全コピーするようなコピーアクティビティを作成するのがいいと思う。

2021年のふりかえりと2022年の抱負

あけましておめでとうございます。今年もよろしくお願いいたします。 2021 年をふりかえり、2022 年の抱負にしたいと思います。

お仕事

2021 年のお仕事は 6 月までと 6 月以降で大きく変わりました。 2 年ほど前に部署を異動してから 2021 年 6 月まではハンズオン講師や PoC といった、「これからデータ分析基盤を導入しようとしている方」に向けて概論を説明したり、提案書を作成するするような営業寄りの活動が多かったです。逆に 6 月以降はデータエンジニアとしてプロジェクトにアサインされ活動しました。

人前に立って話す活動は自分が得意としている部分ではあり楽しかったのですが、データ分析基盤を構築する経験が乏しかったため、説明に説得力をもたせることが出来ていないと思いモヤモヤしていました。そこで、4,5 月辺りからレポート周りの仕事を振ってもらったり、6 月からはプロジェクトに参画し ETL 処理を作成させてもらったりしました。この方向転換は今のところ正解でした。今まで人に話してきたデータ分析基盤の知識が頭に入っているので、日々の具体的な作業を通して答え合わせをするように楽しくプロジェクトに取り組めています。

今のところお客様から高い評価はいただけているようなので、2022 年も引き続き真摯に取り組んでいくとともに Azure 周りの知識の増強を図っていきたいです。データ量が大きいものもあるので、そういった部分にも気を使っていけるようになりたいです。マクロ的な視点でいうと、業務で RDBCSV などの構造化データを扱うことが多いので、半構造化データや非構造化データも扱えるようになりたいですし、別ベンダーや OSS などの製品も触れていきたいです。

ブログ

2021 年はあまり真剣に取り組めなかった一年でした。やめる踏ん切りもつかずダラダラやってしまい、より良くなかったです。来年は力を入れて取り組みますが、そこでダレてしまったら一度更新を休もうと思います。

力を入れて取り組むと言葉にはしていますが、どう取り組んでいくか考えてみました。 まず目標としては月で 5000PV を得られるようにします。ちなみに現状として、直近 3 ヶ月の PV は次でした。

  • 2021 年
    • 10 月
      • 3531PV
    • 11 月
      • 3652PV
    • 12 月
      • 3625PV

目標 5000PV に対して差が約 1500PV ほどあります。つまり、この 1500PV を埋めるための優良な記事を書かなければなりません。SNS で積極的にシェアをすることも PV 増加の要因になると思いますが、クリティカルな部分ではないと考えたので外します。

ここで何を持って優良とするかですが、今回は PV に重きをおいているので、ひとまず PV 数が多いものを優良とします。 現時点で自分のブログの PV 数から優良な記事を段階的に表すと次のようなになると考えています。

    • 月 300PV / 日 10PV
    • 月 100PV / 日 3PV
    • 月 50PV / 日 2PV

様々なところから参照されるぐらい外れ値的な超優良記事を除けば、少し周りの人に聞いた限りだとおそらくだいたいこれぐらいになるのかなと思っています。

「じゃあ毎回 ◎ の記事を書くのか」と言われれば、現実的ではないです。なので、 ▲ の記事を週 1 回書き月に計 200PV を積み重ねていくのが現実的に思います。▲ の記事は 1 日あたり 2PV あればいいということは、自分が 1 日 1 回でも調べたことを記事にしていけば PV が伸びる可能性があります。こう考えると「日々調べたことをまとめればいいんだ」という気持ちにもなり楽ですね。

書く記事の種類についても少し限定させておきたいと思います。今年書く記事は技術解決系と書評に限定させたいと思います。 まず技術解決系と書評はストック型の記事になり、中長期的に PV を得やすいことがあります。逆にフロー系としては勉強会参加系がありますが、情報の鮮度としては短いことがあるので瞬間的な PV 増加は見込めますが継続的には難しいので避けます。余談ですが、競プロ問題解いた系もストック型の記事になるかなと思い、2021 年後半に Project Euler を解いた記事を流していたのですが、あまり流入は得られなかったので一度辞めます。PV が増えてきたりしたらもう一度分析したいと思います。

技術解決は日々出会う可能性がある一方で書評は本を読むスピードに左右されるので、技術解決を週 1 で更新しつつ、書評系を月 1 ぐらいで出せたら良いなと思っています。

※ここで述べたことはあくまで個人的な話です。更新する記事の種類や頻度、すべての部分において自分のペースとやりたいようにやっていただけたらと思います。

趣味や私生活、その他

フットボール

フットサルチームでは守備だけでなく攻撃もやらせて貰う機会が増えシーズン 10 得点でチーム 2 位でした。このために筋トレなどをしていたので結果に結びついてよかったです。アシストもチーム 2 位、守備では最も貢献した人に選ばれ充実な一年だったと思います。ドリブルだったり足元が弱いので、2022 年はそこを改善する努力をしていけたらと思います。まずは体重を減らさないと…

サッカー分析ブログは更新が止まっています。そもそもサッカーを見る機会が減ってしまっているのでなんとかしたいです。

登山

体を動かせて、かつあまり人に出会わない趣味はなにか無いかと探し、結果的に 2021 年は登山をはじめました。道具もしっかり揃えました。まだ東京近郊の小さな山にしか行っていませんがとても楽しいです。2022 年は関東近郊のそこそこ大きい山にも行きたいです。一泊二日ぐらいでも行きたいです。

競馬

無事に 2021 年もプラスでした。金額を一定させる、余計なレースはしない、展開と馬場を意識するなど自分にルールを課した中でうまくいってよかったです。10 場中 9 場(札幌以外)でプラスだったのも嬉しかったです。予想をして当てるのが楽しいので引き続きゆるゆる楽しんでいきたいと思います。

プログラミング系

自分自身エンジニア職にはいますがプログラミングをする機会が少なく、自分の中でずっとコンプレックスになっていたので 4 月からフィヨルドブートキャンプに入会しました。あまり人には公言していなかったのですが、お世話になっておりました。強力なメンター陣がいるので、ここで続かなかったらプログラミングは向いてなかったんだなと諦めるために始めましたが無事に続いております。といいつつ、元日現在システム開発のプラクティスに取り組むのと並行して自作サービスのアイデア出しを実施していますが、自作サービスが全く思いつかず停滞中です。自分は日常で困っていることが少ないんだなということと 0→1 が得意じゃないんだなということがしれてラッキーでした。自作サービスが終わったら卒業なのでもう少しがんばります。

ライフイベント

「自分には自分の人生」と思ってきましたが、周りでライフイベントを進展させる人が増えてきたので、自分もそろそろ真剣に取り組もうと思います。

交流を増やす

昨今の状況もあり、かなり出不精になりました。そしてSNSでも人との交流が減ってしまったように感じています。今年は人との交流を増やしたいです。

なんかあれば書き足す

まとめ

ふりかえりと抱負を書いておきました。 これを読んだ人が健康で過ごせ、何か一つでも実りのある一年になることを祈っています! 今年も頑張りましょう!

math.factorialを使って階乗を計算する

背景

Project Eulermath.factorial()を使う機会が多くなってきたので簡単にまとめる。

math.factorial とは

math.factorial()は標準ライブラリの math に含まれていて、階乗が計算できるシンプルな関数になる。 引数には整数が指定でき、整数以外や負の数を与えた場合は ValueError が発生する。 また、Python3.9 からは floats を指定することが非推奨となる。

docs.python.org

実際の使われ方は以下のようになる。 ライブラリのインポートを除けば 1 行で計算できるのとてもスッキリする。

import math
print(math.factorial(5)) # 5*4*3*2*1 = 120

自作で同じことをしようとすると、以下のようになる。今回は再帰関数で表現した。別の言語で表現するとき、参考になればと思い残しておく。

def factorial(n):
    if n == 1:
        return 1
    else:
        return n * factorial(n-1)

print(factorial(5))

まとめ / 感想

今回はmath.factorial()について簡単にまとめた。 Project Euler が数学の問題を多く扱いっていることもあり、階乗を使った問題も多く出てきていた。なかなか触らない関数と出会う機会も多く楽しいので、引き続き取り組んでいきたい。

【Project Euler】Problem 20 Factorial digit sumをPythonで解く

この問題をPythonで解いた。

#20 Factorial digit sum - Project Euler

日本語の問題文はこちら

n × (n - 1) × ... × 3 × 2 × 1 を n! と表す. 例えば, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800 となる. この数の各桁の合計は 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27 である. では, 100! の各位の数字の和を求めよ.

Problem 20 - PukiWiki

import math
n = 100
print(sum(map(int, str(math.factorial(n)))))