データ処理フローの統合
ここまでの章で,変数・条件分岐・繰り返し・リスト・CSVファイルと, プログラミングの基本となる道具を一つずつ学んできました.これらは,それぞれ 単独でも役に立つが,本当の力を発揮するのは組み合わせたときです. この章では,新しい文法は増やしません.いままで学んだ部品を組み合わせて, 「入力 → 判定 → 集計 → 出力」という 一連のデータ処理フローを自分で組み立てられるように なることを目指す.これは本書の総まとめの章です.
データ処理は4つの段階でできている
第1章で,コンピュータは「入力 → 処理 → 出力」で動くと 学んだ.実際のデータ処理では,まん中の「処理」をもう少しくわしく見ると, たいてい判定(条件で絞る)と集計(数える・合計する・平均する)の 2つに分けられます.つまり,多くのプログラムは次の4段階でできている (図8.1).
- 入力
-
データを受け取ります.キーボードから打ち込む, リストに書いておく,CSVファイルから読み込む,など.
- 判定
-
条件にあてはまるものを選び分ける. 「70点以上か」「30度以上か」などを
ifで調べます. - 集計
-
数をかぞえる,合計する,平均する,最大・最小を 求める,など.
- 出力
-
結果を画面に表示する,ファイルに保存する,など.
たとえば第7章でつくった「合格者数と平均点を出す」プログラムも,この4段階に きれいに分けられます.CSVを読むのが入力,if tensuu >= 70 が 判定,合計や人数を数えるのが集計,print で表示するのが 出力です.いちど身につけてしまえば,どんなデータが相手でも 「この4段階のどこを作っているのか」と考えながら組み立てられます.
多くのプログラムは「入力 → 判定 → 集計 → 出力」の4段階でできています.
これは第1章の「入力 → 処理 → 出力」の,処理をくわしくした形です.
作るときは「いま4段階のどこを書いているか」を意識するとよいでしょう.
入力から判定と集計へ進む
知識
データ処理は入力、判定、集計、出力へ分けられます。各段階の値を追うと、誤りが起きた段階を探せます。
tensuu = [72, 88, 64]
ninzuu = 0
for t in tensuu:
if t >= 70:
ninzuu = ninzuu + 1
print(ninzuu)実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。
出力例
2
ヒントを見る
入力、条件判定、人数の更新、結果の表示を順に区別します。各点数がどの段階で集計へ含まれるか追ってください。
演習の解説
入力は3人の点数、判定は70点以上、集計は人数を1ずつ増やす処理、出力は2です。
___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。
tensuu = [72, 88, 64]
ninzuu = 0
for t in tensuu:
if t ___ 70:
ninzuu = ninzuu + 1
print(ninzuu)ヒントを見る
点数の範囲を決める比較と、人数を増やす更新を分けて追います。条件には合格点そのものも含めます。
虫食いの解説
tensuu = [72, 88, 64]
ninzuu = 0
for t in tensuu:
if t >= 70:
ninzuu = ninzuu + 1
print(ninzuu)空欄には >= が入ります。入力は3人の点数、判定は70点以上、集計は人数を1ずつ増やす処理、出力は2です。
小さな部品を組み合わせる
大きなプログラムを,はじめから一気に書こうとすると,どこから手をつければ よいか分からなくなります.そこで大切なのが,処理を小さな部品に分けて 考えることです.データ処理でよく使う部品は,実はそれほど多くありません.
- 読み込む
-
リストやCSVから1件ずつ取り出す(
for). - 絞る
-
条件にあうものだけを選ぶ(
if). - 数える
-
あてはまる件数をかぞえる(
kaisuu = kaisuu + 1). - 合計・平均する
-
値を足していき,最後に件数で割る.
- 最大・最小を求める
-
いちばん大きい(小さい)値をさがす.
これらの部品は,どれも前の章までに登場したものばかりです.新しい処理を 作るときは,「読み込む・絞る・数える・平均する」のどの部品をどの順に つなげばよいか,と考えればよいでしょう.プログラミングとは,新しい魔法を覚えることでは なく,知っている部品を正しい順に並べることなのです.
データ処理は「読み込む・絞る・数える・合計平均する・最大最小」などの小さな部品でできています.
どの部品も,これまで学んだ
for・if・足し算で作れます.新しい処理は「どの部品をどの順につなぐか」で考えます.
変換と判定をつなぐ
知識
変換、判定、表示という小さな処理を、値を受け渡しながらつなぎます。
moji = "72"
tensuu = int(moji)
print(tensuu >= 70)実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。
出力例
True
ヒントを見る
最初の文字列が数値へ変わってから比較されます。比較結果を表示する行で、点数自体を出すのか真偽を出すのか考えます。
演習の解説
文字列72を整数に変換してから70以上か調べます。比較結果はTrueで、変換しない文字列と整数の大小は比較できません。
___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。
moji = "72"
tensuu = ___(moji)
print(tensuu >= 70)ヒントを見る
最初の値は引用符で囲まれています。大小比較の前に数値へ変える段階が必要です。
虫食いの解説
moji = "72"
tensuu = int(moji)
print(tensuu >= 70)空欄には int が入ります。文字列72を整数に変換してから70以上か調べます。比較結果はTrueで、変換しない文字列と整数の大小は比較できません。
手順を設計してからコードにする
いきなりキーボードに向かうのではなく,まず日本語で手順を書き出す とよいでしょう.第1章で学んだアルゴリズム(あいまいさのない手順)を, 自分の言葉で並べてみるのです.
たとえば「点数の一覧から,合格者の人数と全体の平均を出す」なら,手順は 次のようになります.
(1) 点数を1件ずつ読み込む → (2) 70点以上を数える → (3) 全員の合計から平均を計算する → (4) 結果を表示する
こうして手順がはっきりすれば,あとはそれぞれを知っている部品に 置きかえるだけである(図8.2).「読み込む」は for, 「数える」は if と足し算,「平均する」は合計÷件数,「表示する」は print.日本語の手順とコードが1対1で対応していることに注目してください.
手順を考えずにいきなり書き始めると,途中で「何を作っていたのか」が 分からなくなりやすい.まずは紙でもメモ帳でもよいので,日本語で手順を 書き出すくせをつけるとよいでしょう.手順が正しければ,コードは部品を並べるだけで完成します.
まず日本語で手順(アルゴリズム)を書き出してから,コードに直します.
各手順を,知っている部品(
for・if・足し算・print)に置きかえる.手順とコードが1対1で対応するように作ると,間違いが減る.
日本語の手順を計算へ直す
知識
日本語の手順を先に整理し、それぞれを対応するPythonの文へ直します。合計の初期化も手順に含めます。
tensuu = [72, 88, 64]
goukei = 0
for t in tensuu:
goukei = goukei + t
print(goukei)実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。
出力例
224
ヒントを見る
初期化から各回の加算までを追い、全データを処理したときの合計を求めます。表示の位置も確認してください。
演習の解説
合計を0にする、点数を1個ずつ読む、合計へ加える、表示するという手順から224を求めます。
___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。
tensuu = [72, 88, 64]
goukei = 0
for t in tensuu:
goukei = goukei ___ t
print(goukei)ヒントを見る
各回の点数を、それまでの合計へ合わせる更新を考えます。表示は全点数を処理した後です。
虫食いの解説
tensuu = [72, 88, 64]
goukei = 0
for t in tensuu:
goukei = goukei + t
print(goukei)空欄には + が入ります。合計を0にする、点数を1個ずつ読む、合計へ加える、表示するという手順から224を求めます。
例題1:合格者の人数と全体の平均を出す
設計した手順を,実際にコードにしていこう.まずは点数をプログラムの中の リストに書いておく場合から始める.段階ごとに分けて作り,途中の結果を 確かめながら進めるのがコツです.
部品をつなげて1つにする
「読み込む・数える・合計する」の部品を,1つの繰り返しの中にまとめる. 繰り返しの前に,合計 goukei,人数 ninzuu, 合格者 goukaku をすべて 0 に初期化しておくのを忘れないこと.
tensuu_list = [72, 88, 64, 91, 55, 78]
goukei = 0 # 合計(0から)
ninzuu = 0 # 人数(0から)
goukaku = 0 # 合格者(0から)
for tensuu in tensuu_list:
goukei = goukei + tensuu # 集計:合計に足す
ninzuu = ninzuu + 1 # 集計:人数を数える
if tensuu >= 70: # 判定:70点以上か
goukaku = goukaku + 1 # 集計:合格者を数えるここまでで集計が終わった.繰り返しの中で,合計・人数・合格者数を 同時に集めている点に注目してください.1回まわるごとに,1人ぶんの データが3つの箱に少しずつたまっていく.
平均を計算して出力する
繰り返しが終わったあと(字下げをもどしたところ)で,平均を計算して 結果を表示します.平均は「合計÷人数」です.
heikin = round(goukei / ninzuu, 1) # 平均を小数1桁に丸める
print("人数:", ninzuu, "人")
print("合格者:", goukaku, "人")
print("平均:", heikin, "点")2つのプログラムを続けて実行すると,次のように表示されます.
人数: 6 人 合格者: 4 人 平均: 74.7 点
72・88・91・78の4人が70点以上なので合格者は4人,合計448点を6人で割って 平均は74.7点です.「入力(リスト)→ 判定(if)→ 集計(合計・人数・合格者)→ 出力(print)」という4段階が, そのまま形になっていることを確かめてください.
平均を計算する heikin = goukei / ninzuu は,繰り返しの中に 書いてはいけません.まだ全員ぶんを足し終えていない途中で割っても,正しい平均には なりません.平均の計算は,すべて足し終えたあと(繰り返しの外)で1回だけ行います.
同じことをCSVファイルでやる
データがリストではなくCSVファイルにある場合も,変わるのは入力の部分だけ です.第7章の data/sample/sokutei.csv(名前・身長・体重・点数)を 読み込んで,まったく同じ集計をしてみましょう.
import csv
f = open("data/sample/sokutei.csv", encoding="utf-8")
reader = csv.reader(f)
next(reader) # 入力:ヘッダーをとばす
goukei = 0
ninzuu = 0
goukaku = 0
for gyou in reader:
tensuu = int(gyou[3]) # 入力:3列目を整数に変換
goukei = goukei + tensuu # 集計
ninzuu = ninzuu + 1
if tensuu >= 70: # 判定
goukaku = goukaku + 1
f.close()集計のあと,平均を出して表示する部分は前と同じです.
heikin = round(goukei / ninzuu, 1)
print("合格者:", goukaku, "人")
print("平均:", heikin, "点")実行結果は次のとおりで,リストのときと同じ答えになります.
合格者: 4 人 平均: 74.7 点
リストで書いた版とくらべると,判定・集計・出力の部分はまったく同じで, ちがうのは入力の作り方(open と csv.reader,それに int での数値変換)だけです.データの置き場所がリストでもCSVでも, 処理の組み立て方は変わらない,ということがよく分かる例です.
ひとりずつ合否を表示する
集計して合計を出すだけでなく,名簿の1人1人に,合格か不合格かを そえて表示することもよくあります.これも新しい文法は要りません.繰り返しの中で, if の結果によって表示する文字を変えればよいだけです.名前は gyou[0],点数は gyou[3] にあるので,両方を取り出して使います.
import csv
f = open("data/sample/sokutei.csv", encoding="utf-8")
reader = csv.reader(f)
next(reader) # 入力:ヘッダーをとばす
for gyou in reader:
namae = gyou[0] # 入力:0列目は名前
tensuu = int(gyou[3]) # 入力:3列目を整数に
if tensuu >= 70: # 判定:70点以上か
kekka = "合格"
else:
kekka = "不合格"
print(namae, tensuu, "点", kekka) # 出力:1人ぶん表示
f.close()これを実行すると,名簿の人数だけ行が並ぶ.
佐藤 72 点 合格 鈴木 88 点 合格 高橋 64 点 不合格 田中 91 点 合格 伊藤 55 点 不合格 渡辺 78 点 合格
このプログラムは,前の集計版と骨組みがそっくりです.ちがいは2つ だけです.第1に,合計や人数といった集計の箱を使っていない.1人ぶんを そのつど表示してしまうので,あとまで値をためておく必要がないからです.第2に, if に else を組み合わせ,70点以上なら "合格" を,そうで なければ "不合格" を kekka に代入しています.print はこの kekka をそのまま表示するので,1行で合否がそえられます.
kekka = "合格" の行と print(...) の行の字下げに注目してください. print は for の中(4つ字下げ)にあり,if・else よりは外側(字下げを1段もどす)にあります.もし print を if の中 (8つ字下げ)に入れてしまうと,合格の人しか表示されなくなります.字下げの段数が, そのまま「どの範囲をくり返すか・どの条件のときに動くか」を決めています.
合計・人数・合格者の箱を繰り返しの前に
0で初期化します.繰り返しの中で,集計(足す・数える)と判定(
if)を同時に行います.平均は,繰り返しが終わったあとに「合計÷人数」で求めます.
入力がリストでもCSVでも,判定・集計・出力の組み立ては変わりません.
if/elseで表示する文字を変えれば,1人ずつ合否をそえられます.
合格人数と全員の平均を分ける
知識
合格者数と全体の平均は対象が異なります。全員の合計をためる行を、合格判定の内側へ入れないようにします。
tensuu = [72, 88, 64]
goukei = 0
goukaku = 0
for t in tensuu:
goukei = goukei + t
if t >= 70:
goukaku = goukaku + 1
print(goukaku)
print(goukei / len(tensuu))実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。
出力例
2
74.66666666666667
ヒントを見る
合格者数と全員の合計を、別々の変数で追ってください。平均で割る人数がどの集団の人数かを確認します。
演習の解説
合格者は2人です。平均は不合格の64も含めて224÷3なので、合格者だけの平均80ではありません。
___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。
tensuu = [72, 88, 64]
goukei = 0
goukaku = 0
for t in tensuu:
goukei = goukei + t
if t >= 70:
goukaku = goukaku + 1
print(goukaku)
print(goukei / ___(tensuu))ヒントを見る
平均の分母は合格者数ではなく全データ数です。リスト全体の要素数を調べる処理を使います。
虫食いの解説
tensuu = [72, 88, 64]
goukei = 0
goukaku = 0
for t in tensuu:
goukei = goukei + t
if t >= 70:
goukaku = goukaku + 1
print(goukaku)
print(goukei / len(tensuu))空欄には len が入ります。合格者は2人です。平均は不合格の64も含めて224÷3なので、合格者だけの平均80ではありません。
例題2:気温の記録を集計する
次は気温の記録を題材に,「平均・最高・最低・ある条件を満たす日数」を まとめて出してみましょう.新しい文法は使いません.部品を増やすだけです.
手順を設計する
まず日本語で手順を書き出します.
(1) 1日ずつ気温を読み込む → (2) 合計に足し,日数を数える → (3) いちばん高い・低い気温を更新する → (4) 30度以上の日を数える → (5) 平均を計算して結果を表示する
ここで新しく登場するのが最大・最小を求める部品です. 考え方はこうです.まず最高気温を入れる saidai を,とても小さい値 (ここでは -100)から始めておく.そして1日ずつ気温と見くらべ, いまの気温のほうが大きければ,その値で saidai を更新します. すべて見終わったとき,saidai にはいちばん高い気温が残る.最低気温も, とても大きい値(100)から始めて,小さいほうへ更新していけばよいでしょう.
気温のCSVを集計する
data/sample/kion.csv(日付・気温の2列)を読み込みます.まずファイルを開き, 集計に使う5つの箱を初期化しておく.
import csv
f = open("data/sample/kion.csv", encoding="utf-8")
reader = csv.reader(f)
next(reader) # ヘッダーをとばす
goukei = 0 # 合計
kaisuu = 0 # 日数
saidai = -100 # 最高(とても小さい値から)
saishou = 100 # 最低(とても大きい値から)
mannatsu = 0 # 30度以上の日数続けて,1つの繰り返しの中で5種類の集計を同時に行います.
for gyou in reader:
kion = float(gyou[1]) # 気温は小数なので float
goukei = goukei + kion
kaisuu = kaisuu + 1
if kion > saidai: # 判定:もっと高ければ更新
saidai = kion
if kion < saishou: # 判定:もっと低ければ更新
saishou = kion
if kion >= 30: # 判定:30度以上の日を数える
mannatsu = mannatsu + 1
f.close()集計が終わったら,平均を出して結果をまとめて表示します.
heikin = round(goukei / kaisuu, 1)
print("平均気温:", heikin, "度")
print("最高気温:", saidai, "度")
print("最低気温:", saishou, "度")
print("30度以上の日:", mannatsu, "日")2つのプログラムを続けて実行すると,次のように表示されます.
平均気温: 30.4 度 最高気温: 33.1 度 最低気温: 27.8 度 30度以上の日: 4 日
1つの繰り返しの中で,いくつもの集計を同時に行っている点に注目してください. 合計と日数(平均のため),最高,最低,そして30度以上の日数です.例題1と くらべると,使う部品が「最大・最小を求める」と「条件で数える」に増えただけで, 組み立て方の骨組みはまったく同じです.扱うデータが点数でも気温でも, 身体測定でもアンケートでも,この組み立て方は変わりません.
最高気温の箱を saidai = 0 から始めると,すべての気温が0度より高いときは 正しく動くが,たとえば冬の氷点下の記録だと,本当の最高がマイナスなのに0が 残ってしまう.最大をさがすときは,あり得ないほど小さい値から,最小を さがすときは,あり得ないほど大きい値から始めるのが安全です.
1つの繰り返しの中で,合計・最高・最低・件数を同時に集計できます.
最大は小さい値から,最小は大きい値から始め,見つけるたびに更新します.
小数を含む列は
intではなくfloatで数値に変換します.部品が増えても,「入力 → 判定 → 集計 → 出力」の骨組みは同じ.
気温の境界を含めて数える
知識
気温の集計も点数と同じく、値を順に調べて条件に当てはまる件数を求められます。
kion = [28.5, 31.0, 30.0, 27.5]
atsui = 0
for t in kion:
if t >= 30:
atsui = atsui + 1
print(atsui)実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。
出力例
2
ヒントを見る
気温を1つずつ条件へ当てはめます。ちょうど境界の気温が件数へ含まれるかを確かめてください。
演習の解説
31.0と30.0の2日が30度以上です。境界の30.0を含めるため>=を使います。
___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。
kion = [28.5, 31.0, 30.0, 27.5]
atsui = 0
for t in kion:
if t ___ 30:
atsui = atsui + 1
print(atsui)ヒントを見る
ちょうど境界の気温も対象です。「より高い」だけの条件になっていないか確認してください。
虫食いの解説
kion = [28.5, 31.0, 30.0, 27.5]
atsui = 0
for t in kion:
if t >= 30:
atsui = atsui + 1
print(atsui)空欄には >= が入ります。31.0と30.0の2日が30度以上です。境界の30.0を含めるため>=を使います。
例題3:アンケートの満足度を集計する
最後にもう1つ,題材を変えて練習しておきましょう.授業や催しのあとでよくとる, 5段階アンケート(1:とても不満〜5:とても満足)の集計です. ここでも新しい文法は出てきません.これまでの部品の並べかえだけで作れることを 確かめてください.
手順を設計する
いつものように,まず日本語で手順を書き出します.
(1) 回答を1件ずつ読み込む → (2) 合計に足し,人数を数える → (3) 4以上(満足)の回答を数える → (4) 平均と満足の 割合を計算して表示する
ここで新しく必要になるのは割合(パーセント)の計算ですが,これも 「満足の人数 ÷ 全体の人数 × 100」という,知っている割り算とかけ算 だけでできます.アンケートの回答は,ここではプログラムの中のリストに書いておきます.
回答リストを集計する
回答を1〜5の数で表したリストを用意し,集計用の箱を初期化してから繰り返します.
kotae_list = [4, 5, 3, 4, 2, 5, 4, 1, 3, 5]
goukei = 0 # 評価の合計
ninzuu = 0 # 回答人数
manzoku = 0 # 4以上(満足)の人数
for kotae in kotae_list:
goukei = goukei + kotae # 集計:合計に足す
ninzuu = ninzuu + 1 # 集計:人数を数える
if kotae >= 4: # 判定:4以上を満足とみなす
manzoku = manzoku + 1 # 集計:満足の人数を数える集計が終わったら,平均と満足の割合を計算して表示します.
heikin = round(goukei / ninzuu, 1) # 平均評価
wariai = round(manzoku / ninzuu * 100, 1) # 満足の割合
print("回答人数:", ninzuu, "人")
print("平均評価:", heikin)
print("満足の割合:", wariai, "%")2つのプログラムを続けて実行すると,次のように表示されます.
回答人数: 10 人 平均評価: 3.6 満足の割合: 60.0 %
10人ぶんの評価の合計は36なので平均は3.6,4以上をつけた人は6人なので 割合は60.0 %です.使った部品は「読み込む・合計する・数える・条件で数える」と, 最後の「割合の計算」だけで,例題1とほとんど同じ形であることが分かります.題材が 点数でも気温でもアンケートでも,「入力 → 判定 → 集計 → 出力」の組み立ては変わらないのです.
割合を計算する manzoku / ninzuu * 100 で,もし manzoku と ninzuu が両方とも文字列だったら正しく計算できません.いまはリストに 数(4 や 5)を書いているので変換は必要ありませんが,CSVや input から読んだ回答を使うときは,int で数に直してから集計する ことを忘れないようにしましょう.
アンケート集計も「合計・人数・条件で数える」の組み合わせで作れます.
割合は「あてはまる人数 ÷ 全体 × 100」で求められます.
題材が変わっても,4段階の組み立て方そのものは変わりません.
高い満足度の回答を数える
知識
満足度の集計では、各回答を一度ずつ読み、特定の値に一致する回答を数えます。
manzokudo = [5, 4, 3, 5, 2]
takai = 0
for t in manzokudo:
if t >= 4:
takai = takai + 1
print(takai)実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。
出力例
3
ヒントを見る
満足度の値を足すのか、条件に当てはまる回答を数えるのかを区別します。件数が変わる回を記録してください。
演習の解説
満足度4以上は5、4、5の3回答です。回答の合計19と、高評価の件数3は別の量です。
___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。
manzokudo = [5, 4, 3, 5, 2]
takai = 0
for t in manzokudo:
if t ___ 4:
takai = takai + 1
print(takai)ヒントを見る
境界の評価も高評価へ含めます。回答値を足すのでなく、該当する回答の数を増やします。
虫食いの解説
manzokudo = [5, 4, 3, 5, 2]
takai = 0
for t in manzokudo:
if t >= 4:
takai = takai + 1
print(takai)空欄には >= が入ります。満足度4以上は5、4、5の3回答です。回答の合計19と、高評価の件数3は別の量です。
例題4:買い物の合計とおつりを出す
題材をもう1つ変え,買い物で練習しておきましょう.かごに入れた品物の値段から, 合計金額と,はらったお金からのおつりを出します.さらに,「100円以上の品物が いくつあったか」も同時に数えてみる.ここでも新しい文法は出てきません.これまでの 部品の並べかえだけで作れます.
手順を設計する
いつものように,まず日本語で手順を書き出します.
(1) 値段を1件ずつ読み込む → (2) 合計に足し,品数を数える → (3) 100円以上の品物を数える → (4) はらった金額から合計を引いておつりを 出す → (5) 結果を表示する
ここで新しく必要になるのはおつりの計算だが,これも「はらった 金額 − 合計」という,知っている引き算だけでできます.値段は,ここではプログラムの 中のリストに書いておきます.
値段リストを集計する
品物の値段を並べたリストと,はらう金額を用意し,集計用の箱を初期化してから 繰り返します.
nedan_list = [120, 80, 250, 60, 180]
shiharai = 1000 # はらう金額
goukei = 0 # 値段の合計
kosuu = 0 # 品数
takai = 0 # 100円以上の品数
for nedan in nedan_list:
goukei = goukei + nedan # 集計:合計に足す
kosuu = kosuu + 1 # 集計:品数を数える
if nedan >= 100: # 判定:100円以上か
takai = takai + 1 # 集計:高い品物を数える集計が終わったら,おつりを計算して結果をまとめて表示します.おつりは 「はらった金額 − 合計」です.
otsuri = shiharai - goukei # おつりを計算
print("品数:", kosuu, "点")
print("合計:", goukei, "円")
print("100円以上:", takai, "点")
print("おつり:", otsuri, "円")2つのプログラムを続けて実行すると,次のように表示されます.
品数: 5 点 合計: 690 円 100円以上: 3 点 おつり: 310 円
5点の合計は690円,100円以上は120・250・180の3点,1000円はらったので おつりは310円です.使った部品は「読み込む・合計する・数える・条件で数える」と, 最後の「引き算でおつりを出す」だけで,例題1とほとんど同じ形です.題材が点数でも 気温でもアンケートでも買い物でも,「入力 → 判定 → 集計 → 出力」の組み立ては変わらないのです.
おつりの計算 otsuri = shiharai - goukei は,繰り返しのあと (字下げをもどしたところ)で1回だけ行います.まだ全部の値段を足し終えていない 途中で引いてしまうと,正しいおつりにはなりません.合計を使う計算は,いつも すべて足し終えてからです.
買い物の集計も「合計・品数・条件で数える」の組み合わせで作れます.
おつりは「はらった金額 − 合計」という引き算で求められます.
合計を使う計算(平均・おつり・割合)は,すべて足し終えたあとで行います.
支払額からおつりを求める
知識
買い物では、単価×個数で商品ごとの金額を求め、支払額から合計を引いておつりを求めます。
goukei = 120 * 3 + 80 * 2
azukari = 1000
print(goukei)
print(azukari - goukei)実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。
出力例
520
480
ヒントを見る
商品ごとの代金を求めてから、全商品の合計を作ります。おつりの計算では、引く順番を確認してください。
演習の解説
商品合計は360+160=520円、おつりは1000-520=480円です。おつりの引き算では支払額が左側です。
___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。
goukei = 120 * 3 + 80 * 2
azukari = 1000
print(goukei)
print(azukari ___ goukei)ヒントを見る
商品合計を支払額から差し引きます。引く順番を逆にすると、おつりの符号が変わります。
虫食いの解説
goukei = 120 * 3 + 80 * 2
azukari = 1000
print(goukei)
print(azukari - goukei)空欄には - が入ります。商品合計は360+160=520円、おつりは1000-520=480円です。おつりの引き算では支払額が左側です。
つまずきの総点検
本書を通して何度も注意してきた,つまずきやすいポイントを,ここでまとめて 点検しておこう.プログラムが思うように動かないときは,まずこの一覧を 上から確かめるとよいでしょう.
- 半角と全角
-
カッコ
(\ )・ダブルクォート"\ "・ カンマ,はすべて半角で書きます.全角の「()」や「”」が まじっているとエラーになります.日本語のコメントや文字列の中身は全角でよいでしょう. ==と=-
比べるときは
==(2つ重ねる), 代入するときは=(1つ).if tensuu = 70:はエラーになります. これは初学者が最もくり返しつまずくところです. - 添字は0から
-
リストやCSVの行で,1番目の要素は
gyou[0], 2番目はgyou[1].列の数より大きい添字を書くとIndexError(範囲外)になります. - 型変換
-
CSVや
inputから読んだ値は,見た目が数字でも 文字列です.計算する前にint(整数)やfloat(小数)で変換します.忘れると「足したのにくっつく」 「エラーになる」. - 初期化の位置
-
合計や件数の箱(
goukei = 0など)は, 繰り返しの前に1回だけ書きます.中に書くと毎回0に戻ってしまう. - 字下げ
-
forやifの中身は,半角スペース4つで 字下げします.字下げがずれると,処理の範囲が変わったり,エラーになったりします.
型変換のつまずきを実際に見る
つまずきの中でも特に分かりにくいのが型変換です.言葉で読むより, 一度わざと間違えた結果を見ておくと記憶に残る.次は,CSVから読んだ点数を 数に変換しないまま足し算しようとした,まちがいの例です.
import csv
f = open("data/sample/sokutei.csv", encoding="utf-8")
reader = csv.reader(f)
next(reader)
goukei = 0
for gyou in reader:
goukei = goukei + gyou[3] # ← 文字列のまま足している
f.close()
print(goukei)これを実行すると,計算ではなくエラーになります.
TypeError: unsupported operand type(s) for +: 'int' and 'str'
TypeError(型のエラー)は,整数(int)と文字列 (str)は足せないという意味です.gyou[3] は見た目は 72 でも,ファイルから読んだ時点では文字列 "72" だからです. 直し方は1か所だけで,足す前に int で数に変えればよいでしょう.
goukei = goukei + int(gyou[3]) # ← int で整数に変換
このように,エラーの名前(TypeError)と,足そうとした2つの 型(int と str)がメッセージに出ています.名前を手がかりに 原因の見当をつけ,変換を1つ加えるだけで直せる.「足したのにくっつく・エラーに なる」と感じたら,まず型変換を疑うとよいでしょう.
エラーが出ても,あわてないこと.エラーは「ここを直してね」というコンピュータ からのメッセージです.ValueError なら型変換やヘッダーとばし, IndexError なら添字,FileNotFoundError ならファイルの置き場所と つづり,というように,エラーの名前は原因のヒントになっています.まず上の一覧を 順に確かめれば,多くのつまずきは自分で直せる.
つまずきの定番は「半角全角」「
==と=」「添字0始まり」「型変換」「初期化の位置」「字下げ」.うまく動かないときは,この一覧を上から順に確かめる.
エラーの名前は原因のヒント.こわがらずにメッセージを読みます.
途中経過と最終結果を区別する
知識
字下げが処理の所属を決めます。途中の合計を調べたいときと、最終結果だけを出すときでprintの位置が異なります。
goukei = 0
for t in [72, 88, 64]:
goukei = goukei + t
print(goukei)実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。
出力例
224
ヒントを見る
各回で変わる合計を記録します。表示する行がループの外にある場合に、途中経過も表示されるか考えてください。
演習の解説
printがループの外なので、最後の合計224だけが表示されます。内側に入れると72、160、224の途中経過が表示されます。
___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。
goukei = 0
for t in [72, 88, 64]:
goukei = goukei ___ t
print(goukei)ヒントを見る
合計を更新する文と表示する文の字下げを比べます。ループの外で表示する場合は最終結果だけになります。
虫食いの解説
goukei = 0
for t in [72, 88, 64]:
goukei = goukei + t
print(goukei)空欄には + が入ります。printがループの外なので、最後の合計224だけが表示されます。内側に入れると72、160、224の途中経過が表示されます。
ここからどう学び続けるか
本書では,変数・条件分岐・繰り返し・リスト・CSV,そしてそれらを組み合わせた データ処理フローまでを学んだ.これらは,プログラミングという広い世界の 土台にあたる部分です.土台ができれば,あとは少しずつ積み上げて いける.
これから先へ進むためのヒントを,いくつかあげておく.
身のまわりのデータで試す:自分のテストの点数,毎日の気温, 歩数の記録など,手元のデータをCSVにして,この章のやり方で集計してみる. 自分に関係のあるデータだと,学びが続きやすい.
手順から考えるくせをつける:新しい課題に出あったら,まず日本語で 手順を書き出します.本書で身につけた「設計してからコードにする」流れは, どんな言語・どんな課題でも通用します.
エラーを味方にする:エラーメッセージを読んで自分で直す経験を 重ねるほど,上達は早くなります.エラーは敵ではなく,先生です.
もっと便利な道具を知る:本書では基本の道具だけを使ったが,世の中には 表データをまとめて扱うライブラリ(
pandasなど)や,グラフを描く ライブラリもあります.基本ができたいま,それらも少しずつ読めるはずです.
大きなプログラムも,小さな部品の集まり
これから先,もっと長いプログラムを目にすることもあるだろう.何百行あっても, おそれることはありません.長いプログラムは,本書で学んだ小さな部品が, たくさんつながったものにすぎないからです.本章の例題も,1つ1つは20行に 満たない短い部品に分け,途中で実行結果を確かめながらつないでいった.長い プログラムを読むときも,書くときも,この「小さく分けて,1つずつ確かめる」 やり方がそのまま役に立つ.
たとえば「アンケートを読み込んで集計し,さらに合格・満足の割合を出し,結果を 別のファイルに保存する」といった処理も,分解すれば本章で作った部品の 組み合わせです.入力の部品,判定の部品,集計の部品,出力の部品を,必要な だけ並べればよいでしょう.新しい題材に出あったら,まず「どの部品を,どの順につなぐか」 と考えます.この設計の習慣こそ,本書でいちばん持ち帰ってほしいものです.
長いプログラムも,小さな部品をつなげたものです.
「小さく分けて,途中で確かめながらつなぐ」やり方は,規模が大きくなっても変わりません.
新しい課題は「どの部品を,どの順につなぐか」で考えます.
プログラミングは,スポーツや楽器と同じで,手を動かした分だけ上達します. 本書で学んだ「入力 → 判定 → 集計 → 出力」という 組み立て方を,ぜひ自分のデータで何度も試してください.小さなプログラムでも, 自分で考えて動かせたとき,プログラミングはきっと楽しいものになります.
学んだ基本(変数・分岐・繰り返し・リスト・CSV・フロー)は,すべての土台です.
身のまわりのデータで試し,手順から考え,エラーを味方にすると,学びが続く.
基本ができたら,より便利な道具(
pandasなど)にも進める.
別のデータでも同じ規則を試す
知識
データを変えて同じ手順を試すと、特定の答えを表示しているだけかを確認できます。
tensuu = [70, 69, 100]
ninzuu = 0
for t in tensuu:
if t >= 70:
ninzuu = ninzuu + 1
print(ninzuu)実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。
出力例
2
ヒントを見る
境界の点数、そのすぐ下の点数、それより高い点数を個別に判定します。同じ規則を全データへ適用してください。
演習の解説
70と100の2人が合格です。70を境界として含み、69を除くため、別のデータでも判定のルールを確認できます。
___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。
tensuu = [70, 69, 100]
ninzuu = 0
for t in tensuu:
if t ___ 70:
ninzuu = ninzuu + 1
print(ninzuu)ヒントを見る
境界と、そのすぐ下の値が入っています。どちらを対象へ含めるべきかを先に決めてから条件を書きます。
虫食いの解説
tensuu = [70, 69, 100]
ninzuu = 0
for t in tensuu:
if t >= 70:
ninzuu = ninzuu + 1
print(ninzuu)空欄には >= が入ります。70と100の2人が合格です。70を境界として含み、69を除くため、別のデータでも判定のルールを確認できます。
図で理解する
練習して確かめる
章末演習(10問)
ここには解答を載せていません。
- 章末演習章末演習 1
品物の数量と単価をリストにまとめ、各小計と総額を1回の繰り返しで求めてください。
入力
キーボード入力なし。
nedan = [120, 80, 200]、kosuu = [2, 3, 0]とします。同じ添字の要素が同じ品物の単価と数量です。処理条件
- 指定された2つのリストを作り、
forとrange(len(nedan))で添字を順に取り出します。 - 各小計を掛け算で求め、その小計を合計用変数に加えます。
sum()、zip()、リスト内包表記を使わず、小計や総額を直接書きません。
出力
各品物の小計を各1行で表示したあと、
総額、半角空白1つ、総額の順に1行で表示します。数量0の品物の小計も表示します。計4行で、見出し・単位・空行を加えません。実行例
240 240 0 総額 480ヒントを見る
同じ添字で単価と数量を対応させます。各小計を表示する処理と、その値を総額に加える処理を繰り返しの中に置いてください。
- 指定された2つのリストを作り、
- 章末演習章末演習 2
3日間の販売数を調べ、入力した1日あたりの目標との差と、目標達成日数を求めてください。
入力
1以上100以下の整数
nを1行入力します。input()に案内文を付けません。固定データはhonsuu = [12, 8, 15]です。処理条件
- 入力を
int()で変換し、変数nに入れます。 forで固定リストを走査し、販売数から目標nを引いた差を表示します。- 差が0以上なら目標達成として数えます。
sum()、内包表記、完成した結果の直接表示は使いません。
出力
3日分の差を各1行で半角整数として表示し、最後に
達成日数、半角空白1つ、日数を1行で表示します。目標と同じ販売数の日も達成に含めます。合計4行で余分な表示は加えません。実行例
入力
12出力
0 -4 3 達成日数 2ヒントを見る
日ごとの差は負になる場合もあります。差の表示とは別に、境界の0を含めて達成日を数えます。
- 入力を
- 章末演習章末演習 3
入力した基準点以上の点数をリストから選び、その件数と合計点を求めてください。
入力
1以上100以下の整数
nを1行入力します。input()に案内文を付けません。固定データはtensuu = [60, 80, 60, 95, 0]です。処理条件
- 入力を
int()で変換してnに入れます。 forとifを使い、n以上の要素だけについて件数と合計点を同時に更新します。- 基準と同じ点数を含め、同じ点数が複数あればそれぞれ数えます。
sum()、count()、内包表記を使わず、結果を直接書きません。
出力
件数、半角空白1つ、件数を1行目に表示し、合計点、半角空白1つ、合計点を2行目に表示します。該当する要素がなければ両方0です。要素別の表示・単位・空行は加えません。実行例
入力
60出力
件数 4 合計点 295入力
100出力
件数 0 合計点 0ヒントを見る
条件に合う1件を見つけたとき、更新する値は2つあります。件数には1、合計点にはその点数を加えます。最初の値は該当なしの場合にも使えるようにします。
- 入力を
- 章末演習章末演習 4
リスト
aの要素の中から最小値を求めて表示します。入力
キーボードからの入力はない(
input()は使わない)。次の固定データを使います。a = [5, 9, -3, 4, 0]処理条件
for x in a:の形でリストの要素を順に取り出し,ifでそれまでの最小値より小さければ覚えなおす。- 最小値を覚える変数の初期値は
a[0]とする(リストの値がどんな範囲でも正しく動くようにするため)。 min(),sorted(),sort()は使いません。aは空でないものとします。
出力
最小値:(半角コロン),半角スペース1つ,最小値(半角数字。負の数は半角の-を付ける)を1行で表示します。上に示した行以外の表示(見出し,空行,説明文など)は出しません。境界値:要素が1つだけのリスト(例:
[7])ならその値を表示します。実行例
最小値: -3ヒントを見る
最初の要素を仮の最小値とし,残りの要素と1つずつ比べていく流れを紙に書いてみましょう。比べた結果,どんなときに仮の最小値を入れかえるかを考えます。
- 章末演習章末演習 5
リスト
aの最大値と,その最大値が入っている位置(添字)を求めて表示します。最大値が複数あるときは,最も小さい添字を表示します。入力
キーボードからの入力はない(
input()は使わない)。次の固定データを使います。a = [5, 9, -3, 9, 0]処理条件
for i in range(len(a)):の形で添字を順に取り出し,a[i]で要素を参照します。ifでそれまでの最大値より大きければ,最大値と添字を同時に覚えなおす。初期値はa[0]と添字0とします。max(),index(),sorted(),sort(),enumerate()は使いません。aは空でないものとします。
出力
1行目に
最大値:(半角コロン),半角スペース1つ,最大値。2行目に位置:(半角コロン),半角スペース1つ,添字(0から数える)。数字はすべて半角。合計2行。上に示した行以外の表示(見出し,空行,説明文など)は出しません。実行例
最大値: 9 位置: 1ヒントを見る
値だけでなく位置も覚える必要があるので,要素そのものではなく添字で繰り返す理由を考えます。同じ最大値が後ろにもう1つあるとき,覚えなおしが起こらないようにするには比較演算子をどう選べばよいかを確かめましょう。
- 章末演習章末演習 6
6日分の最高気温のリスト
kionについて,1回の繰り返しで合計と日数を同時に数え,合計と平均を表示します。入力
キーボードからの入力はない(
input()は使わない)。次の固定データを使います。kion = [22.5, 19.0, 25.5, 28.0, 21.5, 23.5]処理条件
for文でリストの要素を順に取り出し,合計と日数を繰り返しの前に用意した変数へ累積します。sum(),len(),statisticsモジュールは使いません。- 平均は繰り返しが終わったあとに合計÷日数で求め,
round(平均, 1)で小数第1位に丸める。合計は丸めません。
出力
1行目に
合計:,2行目に平均:を表示し,それぞれのあとに半角スペース1つと値(半角数字)を続ける。「:」は全角コロン。合計は小数の値なので.0まで表示されます。合計2行。上に示した行以外の表示(見出し,空行,説明文など)は出しません。実行例
合計: 140.0 平均: 23.3ヒントを見る
1周の中で更新する変数が2つあることを確かめ,それぞれの初期化を繰り返しの外のどこに置くかを考えます。平均の計算は,すべての要素を足し終えたあとに1回だけ行います。
- 章末演習章末演習 7
8人分の点数のリスト
tensuuについて,70点以上(ちょうど70点を含む)を合格として,合格者数と全体に対する合格者の割合(%)を表示します。入力
キーボードからの入力はない(
input()は使わない)。次の固定データを使います。tensuu = [85, 62, 74, 58, 91, 70, 45, 88]処理条件
for文とifで合格者を数え,全体の人数も繰り返しの中で数える。len(),sum(),count(),内包表記は使いません。- 割合は繰り返しが終わったあとに「合格者数 ÷ 全体の人数 × 100」で求め,
round(割合, 1)で小数第1位に丸める。
出力
1行目に
合格者数:,半角スペース1つ,人数,半角スペース1つ,人。2行目に割合:,半角スペース1つ,割合,半角スペース1つ,半角の%。「:」は全角コロン,数字は半角。合計2行。上に示した行以外の表示(見出し,空行,説明文など)は出しません。境界値:70点の人は合格に数える。
実行例
合格者数: 5 人 割合: 62.5 %ヒントを見る
数える対象が「全員」と「合格者」の2つあることを確かめ,それぞれの数えあげを `if` の外と中のどちらに置くかを考えます。割合は全員を調べ終えてから計算しましょう。
- 章末演習章末演習 8
6人分の点数のリスト
tensuuについて,1人ずつ点数と評価(A・B・C)を表示します。評価は80点以上がA,60点以上80点未満がB,60点未満がCとします。入力
キーボードからの入力はない(
input()は使わない)。次の固定データを使います。tensuu = [80, 55, 90, 40, 75, 60]処理条件
for文でリストの要素を順に取り出し,繰り返しの中でif・elif・elseを使って評価を決めます。- 評価ごとに別々の
for文を書かない(1回の繰り返しで全員を処理する)。
出力
1人1行で,点数(半角数字),半角スペース1つ,
点,半角スペース1つ,評価(半角英大文字A・B・Cのいずれか)を,リストの順に表示する(合計6行)。上に示した行以外の表示(見出し,空行,説明文など)は出しません。境界値:ちょうど80点はA,ちょうど60点はBとします。
実行例
80 点 A 55 点 C 90 点 A 40 点 C 75 点 B 60 点 Bヒントを見る
条件を上から順に調べる `if`・`elif` では,先に判定した条件に当てはまらなかったことを前提にできます。どの順番で条件を並べると,境目の点数が正しく分かれるかを考えましょう。
- 章末演習章末演習 9
キーボードから気温のデータを件数つきで受け取り,平均・最高・最低を求めて表示します。
入力
1行目にデータの件数
n(1 ≤n≤ 100 の整数),続くn行に気温を1行に1つずつ入力します。気温は −50〜50 の整数で,氷点下は-5のように負の数で入力します。処理条件
input()には案内の文字列を付けない(input()のかっこの中は空にする)。int()で整数に変換します。for文とrange(n)でn回繰り返し,その中で1件ずつ入力を受け取ります。入力をリストにためずに,1回の繰り返しの中で合計の累積と,最高・最低の覚えなおし(if)を行います。sum(),max(),min(),sorted(),list(),statisticsモジュールは使いません。- 平均は繰り返しが終わったあとに求め,
round(平均, 1)で小数第1位に丸める。
出力
1行目
平均:,2行目最高:,3行目最低:のあとに,それぞれ半角スペース1つと値(半角数字,負の数は半角の-付き)を続ける。「:」は全角コロン。平均は整数になる場合も-2.0のように小数第1位まで表示されます。合計3行。入力欄に打ち込んだ値は実行結果に含めません。下の「出力」がプログラムの表示のすべてです。上に示した行以外の表示(見出し,空行,説明文など)は出しません。境界値:すべての気温が負の数でも,最高・最低を正しく表示します。
nが1のときは平均・最高・最低がすべて同じ値になります。実行例
例1
入力:
5 23 19 30 25 21出力:
平均: 23.6 最高: 30 最低: 19例2(すべて負の数)
入力:
3 -2 -5 -1出力:
平均: -2.7 最高: -1 最低: -5ヒントを見る
最初に件数を受け取り,その回数だけ気温を受け取る,という入力の順序を確かめます。次に,最高と最低を覚える変数の初期値を,気温の範囲を手がかりに「最初の1件で必ず覚えなおされる値」にします。すべて負の数の例でも正しく動くか試しましょう。
- 章末演習章末演習 10
キーボードから受験者の点数を件数つきで受け取り,1人ずつ合否を表示したあと,平均点と合格率(%)を表示します。合格は70点以上(ちょうど70点を含む)とします。
入力
1行目に受験者数
n(1 ≤n≤ 100 の整数),続くn行に点数(0〜100の整数)を1行に1つずつ入力します。処理条件
input()には案内の文字列を付けない(input()のかっこの中は空にする)。int()で整数に変換します。for文とrange(n)でn回繰り返し,1件入力するたびにif・elseで合否を判定して表示し,合計と合格者数も同じ繰り返しの中で累積します。sum(),len(),list(),内包表記,statisticsモジュールは使いません。- 平均点と合格率は繰り返しが終わったあとに求め,それぞれ
round(値, 1)で小数第1位に丸める。合格率は「合格者数 ÷n× 100」とします。
出力
最初に1人1行で,点数(半角数字),半角スペース1つ,
点,半角スペース1つ,合格または不合格を入力順にn行表示します。続けて平均点:,半角スペース1つ,平均点の1行と,合格率:,半角スペース1つ,合格率,半角スペース1つ,半角%の1行を表示します。「:」は全角コロン。合計n+ 2 行。入力欄に打ち込んだ値は実行結果に含めません。下の「出力」がプログラムの表示のすべてです。上に示した行以外の表示(見出し,空行,説明文など)は出しません。境界値:70点は合格,69点は不合格とします。合格者がいないときは合格率を
0.0 %と表示します。実行例
例1
入力:
4 85 60 72 90出力:
85 点 合格 60 点 不合格 72 点 合格 90 点 合格 平均点: 76.8 合格率: 75.0 %例2(境目の点数)
入力:
2 70 69出力:
70 点 合格 69 点 不合格 平均点: 69.5 合格率: 50.0 %ヒントを見る
1件ごとに行う処理(入力,判定,表示,累積)と,全員分が終わってから1回だけ行う処理(平均点・合格率の計算と表示)を分けて書き出してから,それぞれを繰り返しの中と外に配置しましょう。