ワーク解答と解答例

プログラムを作成する問題の解答は1つの例です。

1-1 1-2 2-1 2-2 3-1 3-2 4-1 4-2 5-1 5-2
6-1 6-2 7-1 7-2 8-1 8-2 9-1 9-2 10-1 10-2
11-1 11-2 12-1 12-2 13-1 13-2 14-1 14-2 15-1 15-2
16-1 16-2 17-1 17-2 18-1 18-2 19-1 19-2 19-3 20-1 20-2
21-1 21-2 22-1 22-2 23-1 23-2 24-1 24-2 25-1 25-2
26-1 26-2 27-1 27-2 28-1 28-2 29-1 29-2 30-1 30-2

ワーク1-1

1から100の範囲の整数の乱数を10個生成し、その値を出力するプログラムを作りましょう。

      
# wk1-1.py
import random

data = []               # 空のリストを作る

for i in range(10):     # 10回繰り返す
    val = random.randint(1, 100)
    data.append(val)

print('生成された値')
for val in data:
    print(val)
      
    

ワーク1-2

平均が10.0、標準偏差が3.0の乱数が10個入っている配列を生成し、その値を出力するプログラムを作りましょう。

      
# wk1-2.py
import numpy as np

data = np.random.normal(loc=10.0, scale=3.0, size=10)

print('生成された値')
for val in data:
    print(val)
      
    

ワーク2-1

実数値を3個入力してリストに保存し、保存された値を出力するプログラムを作成しましょう。

文字列から実数への変換にはfloat()を使います。値がコンピューター内部に保存される実数に変換される際に誤差が発生する場合があります。

      
# wk2-1.py
data = []

for i in range(3):
    v = input('実数:')
    data.append( float(v) )

print('入力された数')
for v in data:
    print(v)
      
    

ワーク2-2

「quit」という文字列が入力されるまで複数の名前と年齢の情報を入力してリストに保存し、保存された名前を出力するプログラムを作成しましょう。

      
# wk2-2.py
data = []

while 1:
    name = input('名前:')
    if name == 'quit' :
        break
    age = input('年齢:')
    age = int(age)
    data.append( (name, age) )

print('名前\t\t年齢')
for name, age in data:
    print(f"{name:16s}{age:3d}")
      
    

ワーク3-1

ある都市の10年間の人口が次の表のように推移していることを示す折れ線グラフを描くプログラムを作成しましょう。

2014201520162017201820192020202120222023
人口23012240012399824052242032425424256245002486225201
      
# wk3-1.py
import numpy as np
import matplotlib.pyplot as plt

year = range(2014, 2024)
sales = [23012, 24001, 23998, 24052, 24203, 24254, 24256, 24500, 24862, 25201]

plt.plot(year, sales)
plt.xlim(2014, 2023)
plt.ylim(22000, 26000)
plt.xlabel('year', fontsize = 16)
plt.ylabel('sales', fontsize = 16)
plt.grid(color = '0.8')
plt.show()
      
    

ワーク3-2

ある飲食店の月ごとの平均来客数が次の表のように推移しているとします。これを表す折れ線グラフを描くプログラムを作成しましょう。

123456789101112
客数23010516218617514812598113157123256
      
# wk3-2.py
import numpy as np
import matplotlib.pyplot as plt

month = range(1, 13)
custs = [230, 105, 162, 186, 175, 148, 125, 98, 113, 157, 123, 256]

plt.plot(month, custs)
plt.xlim(1, 12)
plt.ylim(0, 300)
plt.xlabel('Month', fontsize = 16)
plt.ylabel('Customers', fontsize = 16)
plt.grid(color = '0.8')
plt.show()
      
    

ワーク4-1

ある飲食店の月ごとの平均来客数が次の表のように推移しているとします。月ごとの売り上げの割合を表す円グラフを描くプログラムを作成しましょう。

123456789101112
客数23010516218617514812598113157123256
      
# wk4-1.py
import matplotlib.pyplot as plt

label = range(1, 13)
custs = [230, 105, 162, 186, 175, 148, 125, 98, 113, 157, 123, 256]

plt.title('Customers by month',fontsize = 16)
plt.pie(custs, counterclock=False, startangle=90, labels=label)
plt.legend(loc='center left', bbox_to_anchor=(1, 0, 0.5, 1))
plt.show()
      
    

ワーク4-2

ある施設に来場した車のメーカー別台数の割合がわかる円グラフを描いてみましょう。メーカー名とそれぞれの台数は任意に定義してかまいません。

      
# wk4-2.py
import matplotlib.pyplot as plt

label = ['Toyota', 'Honda', 'Nissan', 'Mazda', 'others']
x = [252, 165, 148, 67, 58]
color = ["#F7F7F7", "#CCCCCC", "#AAAAAA", "#999999", "#777777"]

plt.title('Percentage by Maker',fontsize = 16)
plt.pie(x, counterclock=False, startangle=90, labels=label, colors=color, \
    shadow=True)
plt.legend(loc='center left', bbox_to_anchor=(1, 0, 0.5, 1))
plt.show()
      
    

ワーク5-1

平均が56、標準偏差が3.5の正規分布に従う100個の体重データの配列を作り、このデータのヒストグラムを描きましょう。

      
# wk6-1
import numpy as np
import matplotlib.pyplot as plt

data = np.random.normal(loc=56, scale=3.5, size=100)

plt.hist(data)
plt.grid(color = '0.8')
plt.show()
      
    

ワーク5-2

平均が158、標準偏差が2.5の正規分布に従う100個の身長データの配列と、平均が56、標準偏差が3.0の正規分布に従う100個の体重データの配列を作り、このデータの散布図を描きましょう。

      
# wk6-2.py
import numpy as np
import matplotlib.pyplot as plt

hdata = np.random.normal(loc=158, scale=2.5, size=100)
wdata = np.random.normal(loc=56, scale=3.0, size=100)

plt.scatter(hdata, wdata)
plt.show()
      
    

身長と体重に相関性を持たせたい場合は、体重データをたとえば次のようにして作ります。

      
wdata = hdata - 165 + np.random.normal(loc=7, scale=3.0, size=100)
      
    

このコードは、生成された身長の値に対して、平均7.0、標準偏差3.0で生成した値を差分として加算します。

ワーク6-1

三次関数のグラフを描いてみましょう。

3次以上の次元が表す線は複雑な曲線になります。3次関数は、たとえば次の式で表現することができます。

y = ax3 + bx2 + cx + d

次の例は、y = 0.8x3 + 1.1x2 + 0.2x - 2のグラフを描く例です。

      
# wk6-1.py
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(-1.0, 1.01, 0.01)
y = 0.8 * x ** 3 + 1.1 * x * x + 0.2 * x - 2

plt.plot(x, y)              # グラフを描画する

plt.grid(color = '0.8')     # グリッドを描画する

plt.show()                  # グラフを表示する
      
    

ワーク6-2

y = cos(x)のグラフを描いてみましょう。

      
# wk6-2.py
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2 * np.pi, 500)
y = np.cos(x)
plt.plot(x,y)
plt.grid(color = '0.8')     # グリッドを描画する
plt.show()
      
    

ワーク7-1

10人分の体重データを定義して、その平均値、中央値、最頻値を求めてみましょう。

      
# wk7-1.py
import numpy as np
data = np.array([61, 58, 57, 60, 57, 58, 62, 48, 55, 58])

print("体重データ:", data)
print("平均値:", np.mean(data))
print("中央値:", np.median(data))
count = np.bincount(data)   # 各値の出現回数をカウントする
md = np.argmax(count)       # 最も頻度が多い数を取得する
print("最頻値=", md)
      
    

ワーク7-2

100人分の体重データを正規分布の乱数で作成して、その平均値、中央値、最頻値を求めてみましょう。

データはnumpy.random.normal()を使って生成します。

      
# wk7-2.py
import numpy as np

rdata = np.random.normal(loc=58.0, scale=2, size=100)
data = []                       # 空のリストを作る
for i in rdata:
    data.append( int(i) )       # 整数にする

print("体重データ:", data)
print("平均値:", np.mean(data))
print("中央値:", np.median(data))
count = np.bincount(data)       # 各値の出現回数をカウントする
md = np.argmax(count)           # 最も頻度が多い数を取得する
print("最頻値=", md)
      
    

ワーク8-1

20人分の体重データを定義して、データを表示した後で、その平均値、分散、標準偏差を求めて表示しましょう。

      
# wk8-1.py
import numpy as np
data = np.array([63, 52, 48, 62, 64, 60, 62, 56,
                  48, 58, 63, 52, 64, 60, 62, 56])
print('体重データ:', data)
ave = np.average(data)          # 平均を求める
print('平均=', ave)
V = np.var(data)                # 分散を求める
print('分散=', V)
sygma = np.std(data)            # 標準偏差を求める
print('標準偏差=', sygma )
      
    

ワーク8-2

100人分の身長データを正規分布の乱数で作成して、データを表示した後で、その平均値、分散、標準偏差を求めて表示しましょう。

      
# wk8-2.py
import numpy as np
rdata = np.random.normal(loc=162.0, scale=2, size=100)
data = []                       # 空のリストを作る
for i in rdata:
    data.append( int(i) )       # 整数にする
print("身長データ:", data)
ave = np.average(data)          # 平均を求める
print('平均=', ave)
V = np.var(data)                # 分散を求める
print('分散=', V)
sygma = np.std(data)            # 標準偏差を求める
print('標準偏差=', sygma )
      
    

ワーク9-1

100人分の身長データを正規分布の乱数で作成して、step9.dataという名前のファイルに保存しましょう。

      
# wk9-1.py
import numpy as np
rdata = np.random.normal(loc=162.0, scale=2, size=100)
data = []                       # 空のリストを作る
for i in rdata:
    data.append( int(i) )       # 整数にする

f = open('step9.data', 'w')
for x in data:
    f.write(str(x) + '\n')

f.close()
      
    

ワーク9-2

ファイルstep9.dataから100人分の身長データを読み込んで、先頭の10人のデータを表示するプログラムを作成しましょう。

      
# wk9-2.py
f = open('step9.data', 'r')
lines = f.readlines()
f.close()

count = 0
for line in lines:
    count += 1
    if count == 1:
        print('最初の10人のデータ')
    if count < 11:
        print(line.strip('\n'))
      
    

ワーク10-1

100人分の身長データ(小数点以下1桁まで)を正規分布の乱数で作成してwork10.dataという名前のファイルに保存しましょう。

      
# wk10-1.py
import numpy as np

data = np.random.normal(loc=160.0, scale=2.5, size=1000)

f = open('work10.data', 'w')
for x in data:
    sx = '{:.1f}\n'.format(x)   # 小数数点以下1桁の文字列にする
    f.write(sx)

f.close()
      
    

ワーク10-2

ファイルwork10.dataから1000人分の身長データを読み込んで、代表値と散布度を計算して表示するプログラムを作成しましょう。

      
# wk10-2.py
import numpy as np

f = open('work10.data', 'r')
lines = f.readlines()
f.close()

data = []                       # 空のリストを作る
for line in lines:
    data.append(float(line.strip('\n')))

ave = np.mean(data)             # 単純平均を計算する
print ('平均=', '{:.1f}'.format(ave));

med = np.median(data)
print ('中央値=', '{:.1f}'.format(med))

print ('最大値=', '{:.1f}'.format(np.max(data)))
print ('最小値=', '{:.1f}'.format(np.min(data)))

count = np.bincount(data)       # 各値の出現回数をカウントする
md = np.argmax(count)           # 最も頻度が多い数(最頻値)を取得する
print ('最頻値=', '{:.1f}'.format(md))

V = np.var(data)                # 分散を求める
print ('分散=', '{:.1f}'.format(V))

sygma = np.std(data)            # データから標準偏差を求める
print ('標準偏差=', '{:.1f}'.format(sygma))
      
    

ワーク11-1

平均60.0、標準偏差3.0の体重データを100個作って、ファイルに保存するプログラムを作ってみましょう。

      
# wk11-1.py
import numpy as np

data = np.random.normal(loc=60.0, scale=3.0, size=100)

f = open('work11.data', 'w')
for x in data:
    sx = '{:.1f}\n'.format(x)   # 小数数点以下1桁の文字列にする
    f.write(sx)

f.close()
      
    

ワーク11-2

ワーク11-1で作製した100個の体重データを含むファイルからデータを読み込んでグラフに表示するプログラムを作ってみましょう。

matplotlib.pyplot.xticks()を指定することでX軸方向の目盛りを指定することができます。

      
# wk11-2.py
import numpy as np
import matplotlib.pyplot as plt

data = []       # 空のリストを作る

f = open ('work11.data', 'r')
lines = f.readlines()
f.close()

for line in lines:
    data.append(float(line))

plt.xticks([55, 60, 65])
plt.hist(data, bins=21)
plt.show()
      
    

ワーク12-1

任意の名前のファイルに保存された一連の値の代表値(最大値、最小値、平均値、中央値、最頻値)を表示するスクリプトを作ってみましょう。

      
# wk12-1.py
import sys
import numpy as np

total = 0
args = sys.argv
if 2 > len(args):
    print('引数を指定してください。')
    sys.exit()

f = open(args[1], 'r')
lines = f.readlines()
f.close()

data = []                       # 空のリストを作る
for line in lines:
    data.append(float(line.strip('\n')))

ave = np.mean(data)             # 単純平均を計算する
print ('平均=', '{:.1f}'.format(ave))

med = np.median(data)
print ('中央値=', '{:.1f}'.format(med))

print ('最大値=', '{:.1f}'.format(np.max(data)))
print ('最小値=', '{:.1f}'.format(np.min(data)))

count = np.bincount(data)       # 各値の出現回数をカウントする
md = np.argmax(count)           # 最も頻度が多い数(最頻値)を取得する
print ('最頻値=', '{:.1f}'.format(md))

V = np.var(data)                # 分散を求める
print ('分散=', '{:.1f}'.format(V))

sygma = np.std(data)            # データから標準偏差を求める
print ('標準偏差=', '{:.1f}'.format(sygma))
      
    

データファイル名がsample10.dataである場合の実行例は、たとえば次のようになります。

      
>python wk12-1.py sample10.data
平均= 160.0
中央値= 159.7
最大値= 172.4
最小値= 150.4
最頻値= 157.0
分散= 18.0
標準偏差= 4.2
      
    

ワーク12-2

任意の名前のファイルに保存された一連の値のヒストグラムを表示するスクリプトを作ってみましょう。

      
# wk12-2.py
import sys
import matplotlib.pyplot as plt

def drawgraph(filename):
    f = open (filename, 'r')
    lines = f.readlines()
    f.close()

    data = []       # 空のリストを作る
    for line in lines:
        data.append(float(line))

    plt.hist(data, bins=21)
    plt.show()
    return ()

if __name__ == '__main__':
    total = 0
    args = sys.argv
    if 1 < len(args):
        total = drawgraph(args[1])
    else:
        print('引数を指定してください。')
        sys.exit()
      
    

データファイル名がsample10.dataである場合は、次のように実行します。

      
>python wk12-2.py sample10.data
      
    

ワーク13-1

文字列'Python\n'をバイト値の並びに変えてみましょう。

文字列'Python\n'の先頭文字'P'は、ASCIIコード表から\050であることがわかります。次の文字'y'は\x79であることがわかります。こうして調べると、'Python\n'は次のような16進数の値を持つバイトの並びになることがわかります。

      
50  79  74  68  6f  6e  0a
      
    

ex13-2.pyのファイル名を変更して各バイトの値を調べることもできます。

ワーク13-2

ファイルを1バイトずつ読み込んでは書き込むことでファイルをコピーするプログラムを作成しましょう。

      
# wk13-2.py
import sys

args = sys.argv
if len(args) < 3:
    print('コピー元とコピー先のファイル名を指定してください。')
    sys.exit()

fi = open(args [1], 'rb')
fo = open(args[2], 'wb')
count = 0
while 1:
    data = fi.read(1)
    if len(data) < 1:
        break

    fo.write(data)
    count = count + 1
fi.close()
fo.close()

print(count, 'バイトコピーしました。')
      
    

ワーク14-1

バイト数が偶数バイトのファイルがあり、奇数バイトを上位バイト、偶数バイトを下位バイトとして2バイトで1つの値を表すとしたときの、代表値と散布度を求めるプログラムを作成しましょう。

たとえば、バイトデータが16進数で「20 3f 54 36...」とつながっている場合、最初のデータ値は0x20 * 0x100 + 0x3fで8255という値であると考えます。

ファイルのサイズ(バイト単位)は、osモジュールのos.path.getsize()で取得できます。

      
# wk14-1.py
import sys
import os
import numpy as np
import matplotlib.pyplot as plt

args = sys.argv
if len(args) < 2:
    print('ファイル名を指定してください。')
    sys.exit()

file_size = os.path.getsize(args [1])
if file_size % 2 == 1:
    print('偶数バイトのファイルを指定してください。')
    sys.exit()

f = open(args [1], 'rb')
bdata = f.read()
f.close()

data = []                       # 空のリストを作る
for i in range(0, file_size-1, 2):
    data.append(int(bdata[i]) * 0x100 + int(bdata[i+1]))

max = np.max(data)
min = np.min(data)
print(f'最大値:{max:04x}')
print(f'最小値:{min:04x}')
print("平均値:", np.mean(data))
print("中央値:", np.median(data))
count = np.bincount(data)       # 各値の出現回数をカウントする
md = np.argmax(count)           # 最も頻度が多い数を取得する
print("最頻値=", md)

V = np.var(data)                # 分散を求める
print('分散=', V)
sygma = np.std(data)            # 標準偏差を求める
print('標準偏差=', sygma )
      
    

ワーク14-2

バイト数が偶数バイトのファイルの、奇数バイトをXの値、偶数バイトをYの値として、散布図を描くプログラムを作成しましょう。

      
# wk14-2.py
import sys
import os
import numpy as np
import matplotlib.pyplot as plt

args = sys.argv
if len(args) < 2:
    print('ファイル名を指定してください。')
    sys.exit()

file_size = os.path.getsize(args [1])
if file_size % 2 == 1:
    print('偶数バイトのファイルを指定してください。')
    sys.exit()

f = open(args [1], 'rb')
data = f.read()
f.close()

xdata = []      # 空のリストを作る
ydata = []      # 空のリストを作る
for i in range(0, file_size-1, 2):
    xdata.append(int(data[i]))
    ydata.append(int(data[i+1]))

plt.scatter(xdata, ydata)
plt.show()
      
    

ワーク15-1

さまざまなファイルを16進ダンプで表示してみましょう。

ex15-1.pyまたは次のwk15-2.pyを使って16進数で表示します。

ファイルサイズが大きい時にはmoreコマンドを使って次のようにすると、数行ずつ見ることができます。

      
>python ex15-1.py sample.mp3 | more
      
    

moreでの表示を途中で中断したいときにはCtrlキーを押しながらCキーを押します。

ワーク15-2

ファイルの内容を、16進数とASCII文字で表示するプログラムを作ってみましょう。

read()でファイルを16バイトずつ読み込んでは16進数とASCII文字で表示するようにすると良いでしょう。

      
data = f.read(16)
      
    

ファイルのバイト数が16の倍数でない場合には、ASCII文字で表示する位置を右にずらす必要があります。

      
# wk15-2.py
from sys import argv
from os.path import exists

if len(argv) != 2:
    print('16進ダンプ表示するファイル名を指定してください。')
    exit()

if not exists(argv[1]):
    print('ファイルが存在しません。')
    exit()

f = open(argv[1], 'rb')

while 1:
    data = f.read(16)
    l = len(data)
    if l < 1:
        break
    for i, x in enumerate(data, 1):
        print(f"{x:02x}",end=' ')
        if i % 8 == 0:
            print(end=' ')
    if l != 16:                 # 16の倍数でない場合に表示を右にずらす
        spc = '   ' * (18-l)
        print(spc, end='')
    if l < 8:
        print('  ', end='')
    elif l !=16:
        print(' ', end='')
    for i, x in enumerate(data, 1):
        if 0x1f < x and x < 0x7f:
            print(f"{x:c}", end='')
        else:
            print(".", end='')
        if i % 16 == 0:         # 16バイトごとに改行する
            print()
        elif i % 8 == 0:        # 8バイトごとに間隔をあける
            print(end=' ')

f.close()
      
    

ワーク16-1

正規分布に従う100個の体重データを含むCSVファイルを作成しましょう。

      
# wk16-1.py
import csv
import numpy as np

data = []       # 空のリストを作る

rdata = np.random.normal(loc=56, scale=3.5, size=100)
for v in rdata:
    data.append(format(v, '#4.1f'))

with open('wk16-1.csv', 'w') as f:
    writer = csv.writer(f)
    writer.writerow(data)
      
    

ワーク16-2

正規分布に従う100個の身長と体重データを含むCSVファイルを作成しましょう。

      
# wk16-2.py
import numpy as np
import matplotlib.pyplot as plt

hdata = np.random.normal(loc=158, scale=2.5, size=100)
wdata = np.random.normal(loc=56, scale=3.0, size=100)

f = open('wk16-2.csv', 'w')
i = 0
for h in hdata:
    f.write(str(h))
    f.write(',')
    f.write(str(wdata[i]))
    f.write('\n')
    i = i+ 1

f.close()
      
    

ワーク17-1

ワーク16-1で作成した正規分布に従う100個の体重データを含むCSVファイルを読み込んで、代表値と散布度を表示するプログラムを作成しましょう。

      
# wk17-1.py
import sys
import csv
import numpy as np

def printValues(data):
    max = np.max(data)
    min = np.min(data)
    print(f'最大値:{max:4.1f}')
    print(f'最小値:{min:4.1f}')
    print("平均値:", np.mean(data))
    print("中央値:", np.median(data))
    count = np.bincount(data)   # 各値の出現回数をカウントする
    md = np.argmax(count)       # 最も頻度が多い数を取得する
    print("最頻値=", md)
    V = np.var(data)            # 分散を求める
    print('分散=', V)
    sygma = np.std(data)        # 標準偏差を求める
    print('標準偏差=', sygma )
    return()

if __name__ == '__main__':
    with open('wk16-1.csv') as f:
        r = csv.reader(f)
        for row in r:
            if len(row) < 1:
                sys.exit()
            data = []           # 空のリストを作る
            for v in row:
                data.append(float(v))
            printValues(data)
      
    

ワーク17-2

Step 16で示したex16.csvのデータから体重データを含むCSVファイルを読み込んで、最大値と最小値および平均値を表示するプログラムを作成しましょう。

リストex16.csvのデータは次のようなものでした。

      
Jimmy, 165, 55
Kenta, 171, 66
Kelly, 164, 55
      
    

ここから体重データだけを取り出して最大値、最小値、平均値を表示するようにします。

      
# wk17-2.py
import csv
import numpy as np

def printValues(data):
    max = np.max(data)
    min = np.min(data)
    print(f'最大値:{max:4.1f}')
    print(f'最小値:{min:4.1f}')
    print("平均値:", np.mean(data))
    return()

if __name__ == '__main__':
    with open('ex16.csv') as f:
        r = csv.reader(f)
        data = []       # 空のリストを作る
        for row in r:
            data.append(float(row[2]))
        printValues(data)
      
    

ワーク18-1

ex18-1.pyで作成したヒストグラムの間隔を調整してより見やすいグラフにしましょう。

グラフの範囲をmatplotlib.pyplot.xlimで指定し、hist()rwidthで棒の幅を、binsで階級(ヒストグラムの棒)の数(デフォルトは10)を指定します。

      
# wk18-1.py
import csv
import matplotlib.pyplot as plt

data = []       # 空のリストを作る

with open('sample.csv') as f:
    r = csv.reader(f)
    for row in r:
        for v in row:
            if len(v) > 0:
                data.append(float(v))

plt.xlim = (155, 175)
plt.hist(data, rwidth=0.9, bins=20)
plt.show()
      
    

ワーク18-2

ワーク16-1で作成した正規分布に従う100個の体重データを含むCSVファイルを読み込んで、ヒストグラムを表示するプログラムを作成しましょう。

      
# wk18-2.py
import csv
import matplotlib.pyplot as plt

data = []       # 空のリストを作る

with open('wk16-1.csv') as f:
    r = csv.reader(f)
    for row in r:
        for v in row:
            if len(v) > 0:
                data.append(float(v))

plt.xlim = (50, 80)
plt.hist(data, bins=30)
plt.show()
      
    

ワーク19-1

sample.xlsxのSheet1のデータをすべて表示するプログラムを作成しましょう。

      
# wk19-1.py
import openpyxl

wb = openpyxl.load_workbook("sample.xlsx")  # ブックを開く
ws = wb["Sheet1"]                           # シートを取得する
#  見出しのセルを取得する
c1 = ws.cell(1, 1)
c2 = ws.cell(1, 2)
c3 = ws.cell(1, 3)
print(f"{c1.value:s}\t\t{c2.value:s}\t{c3.value:s}")

for i in range(2, 6):   #  セルを取得する
    c1 = ws.cell(i, 1)
    c2 = ws.cell(i, 2)
    c3 = ws.cell(i, 3)
    print(f"{c1.value:8s}\t{c2.value:5.1f}{c3.value:8.1f}")
      
    

ワーク19-2

正規分布に従う100個の身長と体重データを含むExcelファイルを作りましょう。

実数xを小数点以下n桁にするときにはround(x, n)を使います。

      
# wk19-2.py
import openpyxl
import numpy as np

hdata = np.random.normal(loc=158, scale=2.5, size=100)
wdata = np.random.normal(loc=56, scale=3.0, size=100)

wb = openpyxl.Workbook()
ws = wb.worksheets[0]   # ワークシートを指定する
i = 0
for h in hdata:
    w = wdata[i]
    i = i+1
    ws.cell(row=i, column=1).value = round(h, 1)
    ws.cell(row=i, column=2).value = round(w, 1)

wb.save('wk19-2.xlsx')  # ファイルに保存する
      
    

ワーク19-3

sample.xlsxのSheet1のデータにデータを追加してwk19-3.xlsxとして保存しましょう。

ここには紙面スペースの都合上2人分のデータを追加するプログラム例を示しますが、もっと多くのデータを追加してみましょう。

      
# wk19-3.py
import openpyxl

wb = openpyxl.load_workbook("sample.xlsx")  # ブックを開くとき
ws = wb.worksheets[0]                       # ワークシートを指定する
ws['A7'] = '斎藤太郎'
ws['B7'] = 164.4
ws['C7'] = 65.8
ws['A8'] = 'Aaron Brendon'
ws['B8'] = 172.5
ws['C8'] = 71.6

wb.save('wk19-3.xlsx')  # ファイルに保存する
      
    

ワーク20-1

ワーク19-2で作成した身長と体重データを含むExcelファイルから体重データを読み込んで、平均値、分散と標準偏差を表示するプログラムを作りましょう。

      
# wk20-1.py
import openpyxl
import numpy as np

wb = openpyxl.load_workbook("wk19-2.xlsx")  # ブックを開く
ws = wb["Sheet"]                            # シートを取得する

data = []                                   # 空のリストを作る
for i in range(1, 101):
    c = ws.cell(i, 2)                       # 体重データのセルを取得する
    data.append(c.value)

print("平均値:", np.mean(data))

V = np.var(data)                            # 分散を求める
print ('分散=', '{:.1f}'.format(V))

sygma = np.std(data)                        # データから標準偏差を求める
print ('標準偏差=', '{:.1f}'.format(sygma))
      
    

ワーク20-2

sample.xlsxのSheet1の体重データを読み込んで、平均値、分散と標準偏差を表示するプログラムを作ってみましょう。

      
# wk20-2.py
import openpyxl
import numpy as np

wb = openpyxl.load_workbook("sample.xlsx")  # ブックを開く
ws = wb["Sheet1"]                           # シートを取得する

data = []                                   # 空のリストを作る
for i in range(2, 6):
    c = ws.cell(i, 3)                       # 体重データのセルを取得する
    data.append(c.value)

print("平均値:", np.mean(data))
V = np.var(data)                            # 分散を求める
print ('分散=', '{:.1f}'.format(V))

sygma = np.std(data)                        # データから標準偏差を求める
print ('標準偏差=', '{:.1f}'.format(sygma))
      
    

ワーク21-1

Step 17で使った身長と体重が含まれるExcelファイルsample.xlsxの体重データからヒストグラム作成しましょう。

プログラムは次のとおりですが、データを増やして実行してみましょう。

      
# wk21-1.py
import matplotlib.pyplot as plt
import openpyxl
import numpy as np

wb = openpyxl.load_workbook("sample.xlsx")  # ブックを開く
ws = wb["Sheet1"]                           # シートを取得する

data = []                                   # 空のリストを作る
for i in range(2, 6):
    c = ws.cell(i, 2)                       # 体重データのセルを取得する
    data.append(c.value)

plt.hist(data)
plt.show()
      
    

ワーク21-2

ワーク19-2で作成した身長と体重データを含むExcelファイルから身長と体重のデータを読み込んで、散布図を表示するプログラムを作成しましょう。

      
# wk21-2.py
import openpyxl
import numpy as np
import matplotlib.pyplot as plt

wb = openpyxl.load_workbook("wk19-2.xlsx")  # ブックを開く
ws = wb["Sheet"]                            # シートを取得する
hdata = []                                  # 空のリストを作る
wdata = []                                  # 空のリストを作る
for i in range(1, 101):
    hdata.append(ws.cell(i, 1).value)       # 身長データのセルを取得する
    wdata.append(ws.cell(i, 2).value)       # 体重データのセルを取得する

plt.scatter(hdata, wdata)
plt.show()
      
    

ワーク22-1

次の中から正しいものを選んでください。

  1. データを集めたものをデータベースと呼ぶ。
  2. データベースは一定の構造でデータを集めたものである。
  3. データベースはファイルに保存できない。
  4. データベースには例外なく同じデータを複数保存できる。

正解:2.

雑多なデータをただ集めただけのものはデータベースとは言いません。データベースのデータは特定の種類のデータで一定の構造を持ちます。また、通常はキーを重複することはできません。

ワーク22-2

次の中から正しいものを選んでください。

  1. キーの値は複数のレコードで重複できる。
  2. 現在操作しているレコードをフィールドという。
  3. プライマリキーは主キーともいい、レコードを識別することに使うことができる。
  4. SQLはホームページを作成するために使う言語である。

正解:3.

ワーク23-1

次の表のデータをデータベースファイルwk23-1.dbに保存しましょう。

      
id	name	height	weight
A0010	Jimmy	165	55
A0021	Kenta	171	66
B0011	Kelly	164	55
B0012	Taro	168	62
B0023	Sally	160	51
      
    
      
# wk23-1.py
import sqlite3

# データベースを作成する
conn=sqlite3.connect("wk23-1.db", isolation_level=None)

# テーブルを作成する
sql="""
CREATE TABLE Member (
  id VARCHAR(4),
  name VARCHAR(20),
  height INTEGER,
  weight INTEGER
);
"""
conn.execute(sql)   # SQLを実行する

conn.execute("INSERT INTO Member VALUES ('A0010','Jimmy',165,55)")
conn.execute("INSERT INTO Member VALUES ('A0021','Kenta',171,66)")
conn.execute("INSERT INTO Member VALUES ('B0011','Kelly',164,55)")
conn.execute("INSERT INTO Member VALUES ('B0012','Taro',168,62)")
conn.execute("INSERT INTO Member VALUES ('B0023','Sally',160,51)")

conn.close()        # データベースを閉じる
      
    

ワーク23-2

正規分布に従う100個の身長と体重データおよびIDを含むデータベースファイルwk23-2.dbを作りましょう。

      
# wk23-2.py
import sqlite3
import numpy as np

hdata = np.random.normal(loc=158, scale=2.5, size=100)
wdata = np.random.normal(loc=56, scale=3.0, size=100)

# データベースを作成する
conn=sqlite3.connect("wk23-2.db", isolation_level=None)

# テーブルを作成する
sql="""
CREATE TABLE Member (
  id VARCHAR(4),
  height INTEGER,
  weight INTEGER
);
"""
conn.execute(sql)   # SQLを実行する

i = 1
for h in hdata:
    sql = "INSERT INTO Member VALUES (" + str(1000+i) + ','  \
        + str(round(hdata[i-1],1)) + ',' + str(round(wdata[i-1],1)) + ")"
    conn.execute(sql)
    i = i + 1

conn.close()        # データベースを閉じる
      
    

ワーク24-1

Step 23で作成したaddress.dbから、Eメールアドレスだけを取り出しましょう。

      
# wk24-1
import sqlite3
conn = sqlite3.connect("address.db", isolation_level=None)
c = conn.cursor()
c.execute("SELECT * FROM Member")
for row in c:
    print(row[3])

conn.close()
      
    

ワーク24-2

ワーク23-2で作成したデータベースファイルwk23-2.dbから、身長が161を超え、かつ、体重が60未満のレコードだけを取り出して表示するプログラムを作成しましょう。

      
# wk24-2.py
import sqlite3
conn = sqlite3.connect("wk23-2.db", isolation_level=None)

c = conn.cursor()
c.execute("SELECT * FROM Member WHERE 161<height AND weight>60")

        for row in c:
        print(row)

        conn.close()
      
    

ワーク25-1

データベースファイルShop.dbを定義してStaffテーブルを作成し、レコードを追加してください。

      
# wk25-1.py
import sqlite3                          # SQLiteのモジュールをインポートする
conn = sqlite3.connect("Shop.db", isolation_level=None)     # Shop.dbに接続する

# テーブルを作成する
# フィールドは、name  age  section
sql="""
CREATE TABLE Staff (
  name VARCHAR(20) PRIMARY KEY,
  age INTEGER,
  section VARCHAR(48)
);
"""
conn.execute(sql)

# データを登録する
conn.execute("INSERT INTO Staff VALUES ('山野健太',25,'販売')")
conn.execute("INSERT INTO Staff VALUES ('花山次郎',28,'管理')")

# データを一括登録する
sql="INSERT INTO Staff VALUES (?, ?, ?)"
data= [("坂田浩二", 27, "仕入れ"), ("小森浩子", 25, "販売")]
conn.executemany(sql, data)

# データを表示する
c = conn.cursor()
c.execute("SELECT * FROM Staff")
for row in c:
    print(row[0], row[1], row[2])

conn.close()
      
    

ワーク25-2

データベースファイルShop.dbから、section(部門)が'管理'のレコードを削除してください。

      
# wk25-2.py
import sqlite3                          # SQLiteのモジュールをインポートする
conn=sqlite3.connect("Shop.db", isolation_level=None)       # Shop.dbに接続する

# 削除前のデータを表示する
print('削除前のデータ')
c=conn.cursor()
c.execute("SELECT * FROM Staff")
for row in c:
    print(row[0], row[1], row[2])

# データを削除する
conn.execute("DELETE FROM Staff WHERE section='管理'")

# 削除後のデータを表示する
print('削除後のデータ')
c=conn.cursor()
c.execute("SELECT * FROM Staff")
for row in c:
    print(row[0], row[1], row[2])

conn.close()
      
    

ワーク26-1

ワーク23-2で作成した身長と体重データを含むファイルwk23-2.dbから体重データを読み込んで、平均値、分散と標準偏差を表示するプログラムを作りましょう。

      
# wk26-1.py
import numpy as np
import sqlite3

conn = sqlite3.connect("wk23-2.db", isolation_level=None)

c = conn.cursor()
c.execute("SELECT * FROM Member")

data = []                       # 空のリストを作る
for row in c:
    data.append(row[2])         # 体重データを取得する

print("平均値:", np.mean(data))

V = np.var(data)                # 分散を求める
print ('分散=', '{:.1f}'.format(V))

sygma = np.std(data)            # データから標準偏差を求める
print ('標準偏差=', '{:.1f}'.format(sygma))

conn.close()
      
    

ワーク26-2

ワーク23-2で作成した身長と体重データを含むファイルwk23-2.dbから身長データを読み込んで、身長が155 cm以上で175 cm以下の人の平均値、分散と標準偏差を表示するプログラムを作りましょう。

      
# wk26-2.py
import numpy as np
import sqlite3

conn = sqlite3.connect("wk23-2.db", isolation_level=None)

c = conn.cursor()
c.execute("SELECT * FROM Member")

data = []                       # 空のリストを作る
for row in c:                   # 身長データを取得する
    if (155.0<row[1]) and (row[1]<175.0):
        data.append(row[1])

        print("平均値:", np.mean(data))

        V = np.var(data)                # 分散を求める
        print ('分散=', '{:.1f}'.format(V))

        sygma = np.std(data)            # データから標準偏差を求める
        print ('標準偏差=', '{:.1f}'.format(sygma))

        conn.close()
      
    

ワーク27-1

ワーク23-2で作った身長と体重が含まれるファイルwk23-2.dbの体重データからヒストグラム作成しましょう。

      
# wk27-1.py
import matplotlib.pyplot as plt
import numpy as np
import sqlite3

conn=sqlite3.connect("wk23-2.db", isolation_level=None)
c = conn.cursor()
c.execute("SELECT * FROM Member")
data = []                       # 空のリストを作る
for row in c:
    data.append(row[2])         # 体重を取得する

conn.close()

plt.hist(data)
plt.show()
      
    

ワーク27-2

ワーク23-2で作った身長と体重が含まれるファイルwk23-2.dbの身長と体重データから、身長が155 cm以上の人の身長と体重の散布図を作成しましょう。

      
# wk27-2.py
import matplotlib.pyplot as plt
import numpy as np
import sqlite3

conn=sqlite3.connect("wk23-2.db", isolation_level=None)
c = conn.cursor()
c.execute("SELECT * FROM Member")
hdata = []                      # 空のリストを作る
wdata = []                      # 空のリストを作る
for row in c:
    if row[1]>155:
        hdata.append(row[1])    # 身長を取得する
        wdata.append(row[2])    # 体重を取得する

conn.close()

plt.scatter(hdata, wdata)
plt.show()
      
    

ワーク28-1

プログラムex28-1.pyはインデントが深いので、あまりインデントしないコードに書き換えてみましょう。

インデントのレベルを減らすために、with文をなくして、ファイルを開いて作業を行った後でファイルを閉じるようにします。

      
# wk28-1.py
import sys
import csv
import openpyxl

wb = openpyxl.Workbook()        # ブックを新規作成する
ws = wb.worksheets[0]
i = 1
f = open('ex16-1.csv')
r = csv.reader(f)
for row in r:
    if len(row) < 1:
        break
    for v in row:
        ws.cell(row=i, column=1).value = v
        i = i + 1

f.close()
wb.save('sex16-1a.xlsx')        # ファイルに保存する
      
    

ワーク28-2

ワーク16-2 で作成した正規分布に従う100個の身長と体重データを含むCSVファイルを、データベースファイルに変換するプログラムを作成しましょう。

      
# wk28-2.py
import sys
import csv
import sqlite3

# データベースを作成する
conn=sqlite3.connect("wk28-2.db", isolation_level=None)

# テーブルを作成する
sql="CREATE TABLE HData (id VARCHAR(4), height REAL, weight REAL);"
conn.execute(sql)                   # SQLを実行する

i = 1
data = []                           # 空のリストを作る
f = open('wk16-2.csv')
r = csv.reader(f)
for row in r:
    if len(row) < 1:
        break
    record = []                     # 空のリストを作る
    record.append(str(100 + i))     # id
    for v in row:
        record.append(round(float(v), 1))
    data.append(record)
    i = i + 1

sql="INSERT INTO HData VALUES (?, ?, ?)"
conn.executemany(sql, data)

f.close()                           # CSVファイルを閉じる
conn.close()                        # データベースを閉じる
      
    

念のため、次のコードでデータベースにデータが保存されているかどうか調べましょう。

      
# wk28-3.py
import sqlite3
conn = sqlite3.connect("wk28-2.db", isolation_level=None)
c = conn.cursor()
c.execute("SELECT * FROM HData")
for row in c:
    print(row)

conn.close()    # データベースを閉じる
      
    

ワーク29-1

ワーク19-2で作成したExcelファイルwk19-2.xlsxのデータをCSVファイルに変換するプログラムを作りましょう。

      
# wk29-1.py
import openpyxl
import csv

wb = openpyxl.load_workbook("wk19-2.xlsx")  # ブックを開く
ws = wb.worksheets[0]                       # シートを取得する
i = 1
data = []
while 1:
    ca = ws.cell(i, 1)                      # 身長のセルを取得する
    if ca.value == None:
        break
    cb = ws.cell(i, 2)                      # 体重のセルを取得する
    data.append([ca.value, cb.value])
    i = i + 1

f = open('wk29-1.csv', 'w', encoding='utf-8', newline='')
writer = csv.writer(f)
writer.writerows(data)
wb.close()
f.close()
      
    

ワーク29-2

ワーク19-2で作成したExcelファイルwk19-2.xlsxのデータをデータベースファイルに変換するプログラムを作りましょう。

      
# wk29-2.py
import openpyxl
import csv

wb = openpyxl.load_workbook("wk19-2.xlsx")  # ブックを開く
ws = wb.worksheets[0]                       # シートを取得する
i = 1
data = []
while 1:
    ca = ws.cell(i, 1)          # 身長のセルを取得する
    if ca.value == None:
        break
    cb = ws.cell(i, 2)          # 体重のセルを取得する
    data.append([str(100+i), ca.value, cb.value])
    i = i + 1

wb.close()                      # ブックを閉じる
# データベースを作成する
conn=sqlite3.connect("wk29-2.db", isolation_level=None)

# テーブルを作成する
sql="CREATE TABLE HWData (id VARCHAR(4), height REAL, weight REAL);"
conn.execute(sql)               # SQLを実行する

sql="INSERT INTO HWData VALUES (?, ?, ?)"
conn.executemany(sql, data)

conn.close()                    # データベースを閉じる
      
    

念のため、次のコードでデータベースにデータが保存されているかどうか調べましょう。

      
# wk29-3.py
import sqlite3
conn = sqlite3.connect("wk29-2.db", isolation_level=None)
c = conn.cursor()
c.execute("SELECT * FROM HWData")
for row in c:
    print(row)

conn.close()    # データベースを閉じる
      
    

ワーク30-1

ワーク23-1で作成したデータベースファイルwk23-1.dbのデータをCSVファイルに変換するプログラムを作りましょう。

wk23-1.dbのイメージは次の表に表すことができます。

      
id	name	height	weight
A0010	Jimmy	165	55
A0021	Kenta	171	66
B0011	Kelly	164	55
B0012	Taro	168	62
B0023	Sally	160	51
      
    
      
# wk30-1.py
import csv
import sqlite3

conn = sqlite3.connect("wk23-1.db", isolation_level=None)
c = conn.cursor()
c.execute("SELECT * FROM Member")
data = []
for row in c:
    data.append(row)

conn.close()    # データベースを閉じる

title = ('id','name','height','weight')
f = open('wk30-1.csv', 'w', encoding='utf-8', newline='')
writer = csv.writer(f)
writer.writerow(title)
writer.writerows(data)
f.close()
      
    

ワーク30-2

ワーク23-1で作成したデータベースファイルwk23-1.dbのデータをCSVファイルに変換するプログラムを作りましょう。

      
# wk30-2.py
import csv
import openpyxl

conn = sqlite3.connect("wk23-1.db", isolation_level=None)
c = conn.cursor()
c.execute("SELECT * FROM Member")
data = []
for row in c:
    data.append(row)

conn.close()                    # データベースを閉じる

wb = openpyxl.Workbook()        # ブックを新規作成する
ws = wb.worksheets[0]
ws.cell(row=1, column=1).value = 'id'
ws.cell(row=1, column=2).value = 'name'
ws.cell(row=1, column=3).value = 'height'
ws.cell(row=1, column=4).value = 'weight'
i = 1
for rec in data:
    ws.cell(row=i+1, column=1).value = rec[0]
    ws.cell(row=i+1, column=2).value = rec[1]
    ws.cell(row=i+1, column=3).value = int(rec[2])
    ws.cell(row=i+1, column=4).value = int(rec[3])
    i = i +1

wb.save('ex30-2.xlsx')          # ファイルに保存する
wb.close()