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

プログラミング

今回はアプリをリリースしたので
そちらのご報告です。

解説動画はこちら



アプリについて


今回作成したアプリはこちらです

・チャンクde英会話

iOS
AppStore


Android
Googleplay

良かったら使ってみてください


アプリの作成方法

Flutterを用いて作成しました

Flutterにした理由は
 1.iOSとAndroid両対応であること
 2.学習コストが低い
 3.文献が豊富で有る

以上の理由からFlutterにしてみました。

それ以外にもアプリを作る方法は
いくらでもありますが、今回は
Flutterを使ってみました。

開発言語がDartになるので
1から勉強することになります。

また、コードやデータなどの大半は
ChatGPTを用いて作成していますので
実質ChatGPTに頼れば
アプリの開発は容易かと思います。

学習開発の期間で2ヶ月くらいでした。



リリースについて

コードを実装しシミュレータや
実機でのテストが終わったら
ビルドを行なってアプリを作り
リリース準備ができます。


その前にアプリストアのアカウントがないと
そもそもリリース出来ないので
アプリストアのアカウント取得が必要です。

これもそこそこ手間と時間が掛かります。

リリース登録をしたら審査が行われますが
審査に通らなければビルドからやり直し
審査に通るまでの繰り返しです。

審査に通ったらようやく
リリース、アプリ配信ができる様になります。

リリース作業を始めてから
アカウント登録とアプリリリースまでで
大体1ヶ月くらい掛かっています。



Flutterについて

動画の方では少しだけ解説していますが
FlutterはiOSとAndroidの両方のアプリを
作成する事ができる開発フレームワークです。

Flutterをインストールしたら
VSCodeなどでコードを書き進める事が
できる様になります。

テストやビルドなども
Flutterコマンドを用いて行う形になります。

この辺りも
VSCodeと合わせておくと
開発が楽になるかなと思います。

どんな感じなのかは
動画の方で解説していますので
参考にしていただければと思います。


最後に

これからアプリ開発を行いたい方にとっては
色々な選択肢があると思いますが
Flutterを使ってアプリを開発したい方が
増えていただけたら幸いです。

Python言語の解説と共に
アプリ開発の方も進めていきますので
要望などあれば是非コメントいただければと思います。

それでは。

プログラミング未経験の方のための
プログラミング学習講座を作成しました

その名も
「1時間で学べるPythonプログラミング」


講義動画はこちら




この講座は初学者の方が
短時間でPython言語を学ぶことのできる
プログラミング学習用の講座です

プログラミングが分からないない方は
Python言語を通じて
プログラミングの基礎を学習できます

講座は動画に加えてGoogle Colabを用いて
手元でコードを動かすことのできます
コードがどう動くのかを確認をしながら
進めていってください

資料はここ:
Google Colabの資料


00:00 1.はじめに
02:13 2.導入方法
02:55 3.GoogleColaboratoryの操作方法
06:19 4.Pythonの計算の基礎
27:27 5.Pythonの制御文
42:14 6.Pythonのクラス
49:11 7.Pythonのその他構文
64:30 8.まとめ

なおPythonチートシートを作成しています。

コーディングに迷った際に役に立ち

WEB検索する時間を無くして

作業時間を効率化できます。

note
Pythonチートシート


 

今回はMLB2023の大谷投手の
全投球データを見てみることとしました。

解説動画はこちら




データの入手先

今回取り扱っているデータは
Baseball Savantというサイトから入手できます。

Baseball Savant


画面の「Pitchers」に名前を入力して「Search」
結果画面の右側にある
「Download Data as Comma Separated Values File」を
クリックするとCSVがダウンロードできます。




データの読み込み

Google Colabでデータを見る際は
事前にダウンロードしたデータを
ファイル置き場にアップロードしておいて下さい。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv('savant_data.csv')
print(df.shape)
df.head()




ピッチャー大谷選手のスタッツ


全球種
name_data=[
  ['Sweeper','スィーパー','スライダーよりも横曲がりの大きいボール'],
  ['4-Seam Fastball','直球','直線的な豪速球(縫い目:シームが4回見える)'],
  ['Cutter','カット・ファスト・ボール','直球とほぼ同じ球速で小さく鋭く変化するボール'],
  ['Split-Finger','フォーク','打者の近くで落下する変化球'],
  ['Sinker','シンカー','投手の利き腕方向に曲がりながら落ちる球種'],
  ['Curveball','カーブ','比較的遅い球速で大きく曲がる球'],
  ['Slider','スライダー','ブレーキがかかった大きく曲がる球'],
  ]
name_df = pd.DataFrame(name_data,columns=["pitch_name","球種名","説明"])
pitch_df = pd.DataFrame(df.pitch_name.value_counts()).reset_index()
pd.merge(pitch_df,name_df,on='pitch_name', how='left')


投球結果
stats_df = pd.DataFrame(df.description.value_counts()).reset_index()
stats_df


ストライクの投球
plt.figure(figsize=(10, 6))
x = df['plate_x']
z = df['plate_z']
d = df['description']
cs = ['blue' if 'strike' in c else 'grey' for c in d]
plt.scatter(x, z, c=cs)
plt.xlim(-10,10)
plt.ylim(-2, 6)
plt.show()
download-2





球種による変化量
plt.figure(figsize=(10, 6))
pitchtypes = ['Sweeper', '4-Seam Fastball', 'Cutter', 
'Split-Finger', 'Sinker', 'Curveball', 'Slider'] colors = ['red', 'brown', 'orange', 'aqua', 'olive', 'magenta', 'lime'] s = set() for index, row in df.iterrows(): x = row['pfx_x'] * (-30.48) # センチ換算(逆方向) z = row['pfx_z'] * ( 30.48) # センチ換算 n = pitchtypes.index(row['pitch_name']) if n not in s: s.add(n) plt.scatter(x, z, color=colors[n], label=row['pitch_name']) else: plt.scatter(x, z, color=colors[n]) plt.legend(loc="upper left", fontsize=12) plt.xlim(-100,100) plt.ylim(-60, 60) plt.show()
download





この様な感じで
投球データを色々な角度から
分析する事ができるデータになっています。

今回紹介した以外にも
たくさんのデータが存在するので
色々遊ぶ事ができると思います。

あそびたい方は
是非データをダウンロードして
こねくりまわしてみて下さい。

それでは。

今回は、犬の名前ランキングの
TOP10の名前の犬に
出会えるまで帰れないロケの
検証シミュレーションです。


解説動画はこちら


 
動画作ってた時は思い出せなかったですが
「スクール革命」という番組で
芸人の「ちゃんぴょんず」が
このロケをしてました。

犬の名前ランキング
トップ10の犬に全部出会うというロケです。

街を歩く犬を散歩している人に声をかけて
何匹出会ったら、全部出会えるのか
プログラムで検証してみましょう。


犬の名前ランキング

まずは犬の名前ランキングです

毎年アンケート調査されている様で
そこのデータを引用します。

import pandas as pd
import numpy as np

df = pd.read_html("https://www.anicom-sompo.co.jp/news-release/2023/20231019/")[0]
df

順位 名前 頭数
0 1位(1) ムギ 1264
1 2位(2) ココ 1091
2 3位(4) ソラ 812
3 4位(3) モカ 786
4 5位(5) マロン 732
5 6位(6) レオ 714
6 7位(8) モコ 676
7 8位(13) ラテ 642
8 9位(7) モモ 641
9 10位(12) チョコ 631


犬の名前ランキングは
こんな感じになっている様です。


シミュレーション

犬は全体で何頭いるか不明なので
TOP10が全体の20%だと仮定します。

まずはこのTOP10をデータ化します。
top_data = []
for i, row in df[["名前","頭数"]].iterrows():
    name = row["名前"]
    num = row["頭数"]
    top_data += [name] * num

print(len(top_data))
7989

残りの80%はハズレですね。
top_num = df["頭数"].sum()
h_num = top_num * 4
h_data = ["ハズレ"] * h_num
print(len(h_data))
31956

data = top_data + h_data
print(len(data))
39945


全体で4万頭ほどのデータになります。

ランダムでシャッフルしてあげると
こんな感じのデータになります。
tmp = data.copy()
np.random.shuffle(tmp)
print(tmp[0:10])
['ハズレ', 'ハズレ', 'ムギ', 'モモ', 'ハズレ', 'ハズレ', 'ムギ', 'ハズレ', 'ハズレ', 'ハズレ']


あとはTOP10の名前に
全部出会えるまで会うだけです。

シミュレーションするプログラムは
こんな感じです。
res = {n:0 for n in df["名前"].values}
count = 0
for name in tmp:
    count+=1
    if "ハズレ"!=name:
        res[name]+=1
        # TOP10全部会ってるか判定
        if all([t>0 for t in res.values()]):
            break
print(count)
210

あとは1回の試行では結果がばらつくので
1万回ほど試行してあげれば
どれくらいの回数で見つかるのかが
分かるはずです。

# 回数チェック関数
def check_count(tmp):
    res = {n:0 for n in df["名前"].values}
    count = 0
    for name in tmp:
        count+=1
        if "ハズレ"!=name:
            res[name]+=1
            # TOP10全部会ってるか判定
            if all([t>0 for t in res.values()]):
                break
    return count

calc_data = []
for i in range(10000):
    tmp = data.copy()
    np.random.shuffle(tmp)
    c = check_count(tmp)
    calc_data.append(c)

calc_df = pd.DataFrame(calc_data,columns=["count"])
calc_df.hist(bins=100)
output_23_1


結果はこんな感じになりました。

大体平均160回くらいで
出会いきれる事になりそうです。

運が良いと数十頭
運が悪いと数百頭

そんな結果でした。

このように、テレビのロケであっても
おおよそのシミュレーションが出来るので

事前にシミュレーションしておくと
諸々の調整がスムーズに行く気がします。

プログラミングでの効率化が
オススメです!!!!

今回はテレビ番組の
ロケをシミュレーションしてみました。

それでは。

今回はPython言語で
様々なソートプログラムを実装して
色々比較してみました。


解説動画はこちら





今回は
ソートプログラムを比較してみる検証です。

用意したソートプログラムは
こんなのです。

1.バブルソート(Bubble Sort)
2.選択ソート(Selection Sort)
3.挿入ソート(Insertion Sort)
4.マージソート(Merge Sort)
5.クイックソート(Quick Sort)
6.ヒープソート(Heap Sort)
7.シェルソート(Shell Sort)



さてひとつづつ見ていきましょう。

バブルソート(Bubble Sort)


隣接する要素を比較して順番が逆であれば交換を行う
比較的単純なソートアルゴリズムで
効率はあまりよくなく、実装が容易です。
# バブルソート
def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        for j in range(0, n-i-1):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
    return arr



選択ソート(Selection Sort)

配列を走査し、最小値を見つけて
先頭の要素と交換することを繰り返すことで
ソートを行うアルゴリズム

バブルソートよりも効率的です。
# 選択ソート
def selection_sort(arr):
    n = len(arr)
    for i in range(n):
        min_index = i
        for j in range(i+1, n):
            if arr[j] < arr[min_index]:
                min_index = j
        arr[i], arr[min_index] = arr[min_index], arr[i]
    return arr


挿入ソート(Insertion Sort)

要素を1つずつ取り出して
適切な位置に挿入していくことで
ソートを行うアルゴリズム

データの量が少ない場合や
すでにほぼソートされている場合には
高速に動作するようです。
# 挿入ソート
def insertion_sort(arr):
    for i in range(1, len(arr)):
        key = arr[i]
        j = i - 1
        while j >= 0 and key < arr[j]:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = key
    return arr


マージソート(Merge Sort)

分割統治法を用いた再帰的なアルゴリズムで
データを分割してソートし、それをマージすることで
ソートを行うアルゴリズム

安定かつ効率的なアルゴリズムであり
大きなデータセットに対しても
高速に動作するそうです。
def merge_sort(arr):
    if len(arr) > 1:
        mid = len(arr) // 2
        left_half = arr[:mid]
        right_half = arr[mid:]

        merge_sort(left_half)
        merge_sort(right_half)

        i = j = k = 0
        while i < len(left_half) and j < len(right_half):
            if left_half[i] < right_half[j]:
                arr[k] = left_half[i]
                i += 1
            else:
                arr[k] = right_half[j]
                j += 1
            k += 1

        while i < len(left_half):
            arr[k] = left_half[i]
            i += 1
            k += 1

        while j < len(right_half):
            arr[k] = right_half[j]
            j += 1
            k += 1
    return arr


クイックソート(Quick Sort)

分割統治法を用いた再帰的なアルゴリズムで
ピボットを選択し、それを基準にデータを分割して
ソートするアルゴリズム

一般的に高速でメモリ効率も良いですが
最悪の場合には効率が落ちることがあるそうです。

再帰を用いたものと
再帰無しバージョンがあり
検証は無しバージョンを使用してます。

# クイックソート(再帰あり)
def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    else:
        pivot = arr[0]
        left = [x for x in arr[1:] if x < pivot]
        right = [x for x in arr[1:] if x >= pivot]
        return quick_sort(left) + [pivot] + quick_sort(right)

再帰無し
# 再帰なし
def quick_sort(arr):
    size = len(arr)
    stack = [(0, size - 1)]
    while stack:
        start, end = stack.pop()
        if start >= end:
            continue

        pivot = arr[end]
        low = start
        high = end - 1

        while low <= high:
            if arr[low] > pivot and arr[high] < pivot:
                arr[low], arr[high] = arr[high], arr[low]
                low += 1
                high -= 1
            if arr[low] <= pivot:
                low += 1
            if arr[high] >= pivot:
                high -= 1

        arr[low], arr[end] = arr[end], arr[low]

        if low - start < end - low:
            stack.append((start, low - 1))
            stack.append((low + 1, end))
        else:
            stack.append((low + 1, end))
            stack.append((start, low - 1))
    return arr




ヒープソート(Heap Sort)

ヒープと呼ばれる特殊なデータ構造を使用して
ソートを行うアルゴリズム

安定でありながらも効率的なソートが可能ですが
実装がやや複雑です。
def heapify(arr, n, i):
    largest = i
    left = 2 * i + 1
    right = 2 * i + 2

    if left < n and arr[i] < arr[left]:
        largest = left

    if right < n and arr[largest] < arr[right]:
        largest = right

    if largest != i:
        arr[i], arr[largest] = arr[largest], arr[i]
        heapify(arr, n, largest)

# ヒープソート
def heap_sort(arr):
    n = len(arr)

    for i in range(n // 2 - 1, -1, -1):
        heapify(arr, n, i)

    for i in range(n - 1, 0, -1):
        arr[i], arr[0] = arr[0], arr[i]
        heapify(arr, i, 0)
    return arr


シェルソート(Shell Sort)

挿入ソートの改良版であり
データを一定の間隔で分割して
ソートを行うアルゴリズム

間隔を縮めながら繰り返し処理を行うことで
最終的にソートされた配列が得られます。
# シェルソート
def shell_sort(arr):
    n = len(arr)
    gap = n // 2

    while gap > 0:
        for i in range(gap, n):
            temp = arr[i]
            j = i
            while j >= gap and arr[j - gap] > temp:
                arr[j] = arr[j - gap]
                j -= gap
            arr[j] = temp
        gap //= 2
    return arr


速度比較

これら7つのソートプログラムを用いて
速度を比較してみましょう。

こちらのコードで比較検証を行いました。
import numpy as np
import time
import sys
sys.setrecursionlimit(20000)

# 関数実行時間チェック
def time_check(name,func,n):
    start_time = time.time()
    val = func(n);
    end_time = time.time()
    print(name, end_time - start_time)

# ソート比較
def compare_sort(n):
    # ソート対象のリスト生成
    arr = [1 for _ in range(n)]
    np.random.shuffle(arr)
    
    # 各ソートアルゴリズムの実行時間計測
    #time_check("バブルソート" , bubble_sort, arr.copy())
    #time_check("選択ソート" , selection_sort, arr.copy())
    time_check("挿入ソート" , insertion_sort, arr.copy())
    #time_check("マージソート" , merge_sort, arr.copy())
    time_check("クイックソート" , quick_sort, arr.copy())
    time_check("ヒープソート" , heap_sort, arr.copy())
    time_check("シェルソート" , shell_sort, arr.copy())

compare_sort(1000)




最後に


とまあ、ソートプログラムを書くのは
プログラミングのお勉強には良いですが
業務上の実益はほぼほぼ無いですねー

そもそもPythonの組み込みソートは
圧倒的に性能が良く

数10万件程度だと
誤差の範囲で終わってしまうので
ソートを業務で実装することは
余り無いですね。

超大規模なデータを用いるような
大掛かりなプロジェクトでなければ
ソートに手を入れて高速化をはかるような
案件に出会えないですかね。

興味がある方は
突き詰めてみるのも面白いかもです。

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

このページのトップヘ