2022年11月19日土曜日

form要素のinput type="button" と button要素のJavaScriptでの挙動の違い

 フォーム要素でボタンを使用する場合、現在ではbutton要素が推奨されてます。

理由はそこら中で書いてありますが、CSSで疑似要素が使えたり、デザイン性で柔軟だからです。

ここではJavaScriptによる違いを書きます。


まずは、何もないbutton要素

  

何も指定しないと、type="submit"と同じ送信になり、formのaction属性と同じになります。

なのでtype="button"にしたい場合は属性を書かなければなりません。

button要素の中のテキストを取得したい場合は、input要素のようにvalueでは取得できません。button要素の文字は、タグで挟まれてるのでtextContentで取得します。


button要素でカウンターを作る例

  

冷静に考えたら分かりますね。

submitで値を送信したい場合は、そのままvalue属性が書けます。

2022年9月15日木曜日

PythonのMeCab使用でエラーが出る

 MeCabは日本語形態素解析システムの主要パッケージで、日本語解析によく使われます

しかしバージョンが合ってないとただimportしただけではエラーが出ます。


Python3の pip install mecab でエラーが出た場合は



$ pip install mecab-python3

$ pip install unidic-lite


でインストールしてください。


unidic-liteは辞書です。


----------------------------------------------------------


Failed initializing MeCab. Please see the README for possible solutions:


    https://github.com/SamuraiT/mecab-python3#common-issues


If you are still having trouble, please file an issue here, and include the

ERROR DETAILS below:


    https://github.com/SamuraiT/mecab-python3/issues


issueを英語で書く必要はありません。


------------------- ERROR DETAILS ------------------------


のようなエラーが出た場合は辞書がインストールされてません

2022年8月28日日曜日

線形回帰を求める(2)

前回は散布図で、都道府県別人口と平均年収をプロットしました。 後は線形回帰分析するだけです。 線形回帰はsklearnライブラリを使用することで簡単に分析できます。
from sklearn.linear_model import LinearRegression

X = df3[['人口']]
y = df3['平均年収']

# モデルの作成
model = LinearRegression()

model.fit(X, y)


print("傾き: %f" % model.coef_)
print("切片: %f" % model.intercept_)
print()
print("決定係数: %f" % model.score(X, y))


y = ax + b 

傾き: 0.124986 
切片: 4101341.031155 

決定係数: 0.605080


sklearnを使うだけで、簡単に単回帰分析出来ます。

predictを使い回帰直線を引きます。

人口と平均年収の関係はありそうですね。

predict = model.predict(X)

plt.plot(x, predict, color="coral")

全コード
#! /usr/bin/env python

# -*- coding:utf-8 -*-

#
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
from sklearn.linear_model import LinearRegression

#日本円表示を数値に
def currencyToNumber(val):
    # 万と千以下に分ける
    man, sen = val.split("万")

    #円を取り除き,千以下を0埋め
    sen = sen.replace("円", "")
    sen = sen.zfill(4)

    man += sen
    return int(man)
    

# 数値のカンマを取り除く
def dropComma(val):
    val = val.replace(",", "")

    return float(val)

data1 = "../data/prefecture1.csv"
data2 = "../data/income_pref.csv"

df1 = pd.read_csv(data1)
df2 = pd.read_csv(data2)

print(df1.head())
print()
print(df2.head())
print()

df3 = pd.merge(df1, df2)

print(df3.head())
print()

df3['平均年収'] = df3['平均年収'].apply(currencyToNumber)
df3['人口'] = df3['人口'].apply(dropComma)

x = df3['人口']
X = df3[['人口']]
y = df3['平均年収']


# モデルの作成
model = LinearRegression()

model.fit(X, y)


print("傾き: %f" % model.coef_)
print("切片: %f" % model.intercept_)
print()
print("決定係数: %f" % model.score(X, y))

pref_name = df3['都道府県']

plt.figure(figsize=(16, 10))

predict = model.predict(X)


plt.title("人口と平均年収のグラフ", fontsize=24)
plt.scatter(x, y)
plt.grid()

plt.xlabel("人口(人)", fontsize=18)
plt.ylabel("平均年収(円)", fontsize=18)

plt.plot(x, predict, color="coral")

for i, pref in enumerate(pref_name):
    plt.annotate(pref, (x[i], y[i]))

nums = plt.gca().get_yticks()
plt.gca().set_yticklabels(['{:,.0f}'.format(i) for i in nums])
nums = plt.gca().get_xticks()
plt.gca().set_xticklabels(['{:,.0f}'.format(i) for i in nums])

out = "img/prefecture_data1.png"
plt.savefig(out)
plt.show()

線形回帰を求める(1)

 色々なデータに触れると、相関関係があるのか確かめたくなります。

最も簡単な分析が線形回帰でよく使われています。

今回は、こちらのデータを使い都道府県と平均年収の関係を使って簡単なテストをしてみます。

import pandas as pd

data1 = "prefecture1.csv"
data2 = "income_pref.csv"

df1 = pd.read_csv(data1)
df2 = pd.read_csv(data2)

print(df1.head())
print(df2.head())

  都道府県 県庁所在地          人口          面積     人口密度
0  北海道   札幌市  5,181,776   83,424.41    66.08 
1  青森県   青森市  1,221,288    9,645.62   126.62 
2  岩手県   盛岡市  1,196,277   15,275.01    78.32 
3  宮城県   仙台市  2,290,036    7,282.29   314.47 
4  秋田県   秋田市    944,902   11,637.52    81.19 

   順位  都道府県       平均年収
0  1位   東京都  584万9300円
1  2位  神奈川県  541万5500円
2  3位   愛知県   524万400円
3  4位   大阪府  511万8600円
4  5位   兵庫県  495万2100円


データフレームをマージし、数値で処理出来るようにコンマなど取り払います。
説明変数xは人口、目的変数yは平均年収の関係を調べましょう。



# データのマージ
df3 = pd.merge(df1, df2)



#日本円表示を数値に
def currencyToNumber(val):
    # 万と千以下に分ける
    man, sen = val.split("万")

    #円を取り除き,千以下を0埋め
    sen = sen.replace("円", "")
    sen = sen.zfill(4)

    man += sen
    return int(man)
    

# 数値のカンマを取り除く
def dropComma(val):
    val = val.replace(",", "")

    return float(val)
    
    
    
# 関数を適用して数値にする
df3['平均年収'] = df3['平均年収'].apply(currencyToNumber)
df3['人口'] = df3['人口'].apply(dropComma)

# プロットする場合はSeriesで小文字のx
x = df3['人口']
# 線形回帰する場合はDataFrameで大文字のX
X = df3[['人口']]

# 目的変数y
y = df3['平均年収']


出来上がったデータを散布図としてプロットします。

import matplotlib.pyplot as plt
import japanize_matplotlib


# 県名が見やすいように大きめのグラフに
plt.figure(figsize=(16, 10))


plt.title("人口と平均年収のグラフ", fontsize=24)

#散布図
plt.scatter(x, y)
plt.grid()

plt.xlabel("人口(人)", fontsize=18)
plt.ylabel("平均年収(円)", fontsize=18)

# 点それぞれに中訳を入れる annotate
pref_name = df3['都道府県']

for i, pref in enumerate(pref_name):
    plt.annotate(pref, (x[i], y[i]))

# 数値が大きいと指数表示になるので、分かりやすく整数表示にする
nums = plt.gca().get_yticks()
plt.gca().set_yticklabels(['{:,.0f}'.format(i) for i in nums])
nums = plt.gca().get_xticks()
plt.gca().set_xticklabels(['{:,.0f}'.format(i) for i in nums])


plt.show()

2022年6月17日金曜日

NBA選手データを整える

 NBAはデータを豊富に提供しているので分析に適しています。

ただし、身長や体重が日本と異なる表記なので、日本で分かりやすいようにデータを変換してみます。

ついでに欠損値除去や微調整してデータを取り扱い安くします。


まず、元データ player_data.csv の中身を確認します。

filename = "player_data.csv"

df = pd.read_csv(filename)

print(df.head())
print()
print(df.shape)
print()
print(df.info())


                  name  year_start  year_end position height  weight        birth_date                                college

0       Alaa Abdelnaby        1991      1995      F-C   6-10   240.0     June 24, 1968                        Duke University

1      Zaid Abdul-Aziz        1969      1978      C-F    6-9   235.0     April 7, 1946                  Iowa State University

2  Kareem Abdul-Jabbar        1970      1989        C    7-2   225.0    April 16, 1947  University of California, Los Angeles

3   Mahmoud Abdul-Rauf        1991      2001        G    6-1   162.0     March 9, 1969             Louisiana State University

4    Tariq Abdul-Wahad        1998      2003        F    6-6   223.0  November 3, 1974              San Jose State University


(4550, 8)


<class 'pandas.core.frame.DataFrame'>

RangeIndex: 4550 entries, 0 to 4549

Data columns (total 8 columns):

 #   Column      Non-Null Count  Dtype  

---  ------      --------------  -----  

 0   name        4550 non-null   object 

 1   year_start  4550 non-null   int64  

 2   year_end    4550 non-null   int64  

 3   position    4549 non-null   object 

 4   height      4549 non-null   object 

 5   weight      4544 non-null   float64

 6   birth_date  4519 non-null   object 

 7   college     4248 non-null   object 

dtypes: float64(1), int64(2), object(5)


データは4550件、birth_dateやweightに欠損値が散見されます。


print(df[df['weight'].isnull()])
print()
print(df[df['birth_date'].isnull()].sort_values('year_end', ascending=False))

df2 = df.dropna(how="any")
欠損値データを確認すると昔の人ばかりなので、昔の年代を分析しない場合は削除して構わないでしょう。dropna(how="any")で欠損値を取り除いたデータフレームにします。


# 1foot = 30.48, 1inch = 2.54cm
FOOT= 30.48
INCH = 2.54

# 1pond = 0.4536kg
LB = 0.4536

# フィートをセンチに
def toCenti(height):

    ft, inc = height.split("-")
    cent = int(ft) * FOOT + int(inc) * INCH

    return round(cent, 2)


# ポンドをキログラムに
def toKilogram(weight):

    kg = weight * LB
    
    return round(kg, 2)
    
 
# 以上の関数を身長体重データに適用させる
df2['height'] = df2['height'].apply(toCenti)
df2['weight'] = df2['weight'].apply(toKilogram)


print(df2.head())
print()
print(df2.shape)



                  name  year_start  year_end position  height  weight        birth_date                                college
0       Alaa Abdelnaby        1991      1995      F-C  208.28  108.86     June 24, 1968                        Duke University
1      Zaid Abdul-Aziz        1969      1978      C-F  205.74  106.60     April 7, 1946                  Iowa State University
2  Kareem Abdul-Jabbar        1970      1989        C  218.44  102.06    April 16, 1947  University of California, Los Angeles
3   Mahmoud Abdul-Rauf        1991      2001        G  185.42   73.48     March 9, 1969             Louisiana State University
4    Tariq Abdul-Wahad        1998      2003        F  198.12  101.15  November 3, 1974              San Jose State University

(4213, 8)

変換できました。

player_data_a.csv
完成データは 

2022年6月11日土曜日

matplotlibで一次関数グラフを作る

前回、matplotlibで方眼紙の様な正方形グリッドが作れたら、数学の関数グラフも容易に作れます。

matplotlibはデータをプロットするライブラリなので式をそのままグラフにするのはひと工夫必要です。

今度はオブジェクト指向で関数グラフを作り、一次関数をプロットします。


# オブジェクト指向でグラフ作成
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
 
# これで正方形になります。
ax.set_aspect('equal', adjustable='box')

# 表示する幅
ax.set_xlim(-10, 11)
ax.set_ylim(-10, 11)

# グラフの刻み
ax.set_xticks(np.arange(-10, 10, 5))
ax.set_yticks(np.arange(-10, 10, 5))
 
# 補助線をonにします
ax.minorticks_on() 

# グリッドの主線と補助線
ax.grid(which="major", color="black", alpha=0.5)
ax.grid(which="minor", color="gray", linestyle="--", alpha=0.5)

# 数値表示を0に合わせます。
ax.spines['bottom'].set_position("zero")
ax.spines['left'].set_position("zero")
 

今回はオブジェクト指向のプロットなので若干書き方が違います。特に正方形にするには set_aspect('equal', adjustable='box')という指定をします。 またグラフの数値を0に合わせるため、spines.set_position 関数で zero を指定します。

関数グラフの方眼紙が出来たら、後は一次関数のデータを生成する関数を作ればいいだけ。

# 一次関数のデータを作る関数 
def linear(a, b, ran=np.arange(-10,10)):

    arr = []
    for x in ran:
        y = x*a + b
        arr.append(y)

	# 式から配列データを返します。
    return arr
これを応用すれば二次関数や他の関数もプロットできますね。


[完成形]
#! /usr/bin/env python

# -*- coding:utf-8 -*-
 
 
import numpy as np
import matplotlib.pyplot as plt


# 一次関数のデータを作る関数 
def linear(a, b, ran=np.arange(-10,10)):

    arr = []
    for x in ran:
        y = x*a + b
        arr.append(y)

	# 式から配列データを返します。
    return arr

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
 
# これで正方形になります。
ax.set_aspect('equal', adjustable='box')

# 表示する幅
ax.set_xlim(-10, 11)
ax.set_ylim(-10, 11)

# グラフの刻み
ax.set_xticks(np.arange(-10, 10, 5))
ax.set_yticks(np.arange(-10, 10, 5))
 
# 補助線をonにします
ax.minorticks_on() 

# グリッドの主線と補助線
ax.grid(which="major", color="black", alpha=0.5)
ax.grid(which="minor", color="gray", linestyle="--", alpha=0.5)

# 数値表示を0に合わせます。
ax.spines['bottom'].set_position("zero")
ax.spines['left'].set_position("zero")

x = np.arange(-10, 10)

# y = 2x + 3の一次関数を生成
y = linear(2, 3, x)
ax.plot(x, y)


plt.show()

2022年6月9日木曜日

matplotlibで方眼紙のようなグリッドを作る

Pythonのmatplotlibはグラフ描画のためのライブラリですが、描画はデータによって自動的に調整されるので、時には方眼紙のように正確なグリッドが欲しい場合もあります。

正方形の方眼紙のようなグリッドは、plt.axis("square")で正方形に、ticksでマス目を刻みます。

#! /usr/bin/env python

# -*- coding:utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

# 正方形で表示
plt.axis("square")

# 表示範囲の指定
plt.xlim(-10, 10)
plt.ylim(-10, 10)

# 値の刻み
plt.xticks(np.arange(-10, 11, 5))
plt.yticks(np.arange(-10, 11, 5))

#grid マイナー線の指定をします
plt.minorticks_on()
plt.grid()
# マイナー線は破線で透明度50%
plt.grid(which="minor", color="gray", linestyle="--", alpha=0.5)

plt.show()
 
 
ポイントはaxis("square")です。これで数値通りの大きさで表示されます。
あとはxlimでX軸の、ylimでY軸のグラフの範囲、ticksで表示するメモリ数値の刻みを指定します。
グリッドの線はgrid関数で指定しますが、主線だけでなく副線も表示したい場合はminorticks_on関数を呼び出して表示します。
副線は同じgrid関数でwhich="minor"で呼び出します。
あとは"--"で破線、alphaで透明度など指定して好みの方眼紙に調整してください。



以上のようなグラフになります。


NBAの1試合平均チームスタッツ (2025-26レギュラーシーズン)

前回 の元となったデータ、チーム毎の各スタッツ平均です。   team games w l win% PTS AST BLK STL ...