プログラミング演習・14章版 第7章 CSVとファイルの扱い
教材コード

ファイル(CSV)の読み込みと集計・整形

これまでの章では,プログラムの中に数値や文字列を直接書いてきた.しかし, 実際のデータは,健康診断の身体測定の記録や,テストの点数一覧のように, たくさんの行と列でできた表の形で用意されていることがほとんどです. そして,そうした表の多くはCSVファイルという形で 保存されています.

この章では,CSVファイルをプログラムから読み込み,合計や平均を 計算したり,条件にあてはまるものを数えたりする方法を学ぶ. プログラムの大きな流れは「読み込む → 集計・整形する → 出力する」の3段階である(図7.1).これは第1章で学んだ 「入力 → 処理 → 出力」の,ファイルを使った具体版だと 思えばよいでしょう.

CSVを扱うプログラムの流れ:読み込む → 集計・整形する → 出力する

CSVファイルってなんだろう

CSVファイルとは,データをカンマ「,」で区切って 並べたテキストファイルのことです.CSV は “Comma-Separated Values” (カンマで区切られた値)の頭文字をとった名前です.

たとえば,ある体力測定の記録を考えてみましょう.名前・身長・体重・点数を 人数分ならべると,次のようなテキストになります.

実行結果の例
namae,shinchou,taijuu,tensuu
佐藤,158.2,50.1,72
鈴木,162.5,55.4,88
高橋,155.0,48.7,64

1行が1人分のデータにあたり,カンマで区切られた1つ1つが各列の値です. これは,表計算ソフトで開く表(行と列)とまったく同じ中身である (図7.2).実際,表計算ソフトには「CSV形式で保存」という メニューがあり,表を CSV ファイルに書き出したり,逆に CSV ファイルを 表として開いたりできます.

CSVファイル(テキスト)は表(行と列)と同じもの

いちばん上の行(namae,shinchou,taijuu,tensuu)は,それぞれの列が何を 表すかを書いた見出しの行です.これをヘッダー(ヘッダー行)と いう.2行目から下が,実際のデータの行です.

この章では,上のデータを data/sample/sokutei.csv というファイル名で 用意してあるものとして話を進める.自分のプログラムと同じ場所に data フォルダがあり,その中の sample フォルダに sokutei.csv が置かれている,という想定です.

  • CSVファイルは,データをカンマ「,」で区切って並べたテキストファイルです.

  • 1行が1件分のデータ,カンマ区切りの1つ1つが各列の値です.

  • 表計算ソフトの「表(行と列)」とCSVファイルは同じ中身を指す.

  • 先頭の見出し行をヘッダー(ヘッダー行)といいます.

CSVの1行を列に分ける

知識

CSVでは1行が1件、カンマで区切った各部分が列です。まず1行の列を取り出す操作を確かめます。

row = "佐藤,158.2,50.1,72".split(",")
print(row)
そのまま演習CSVの1行を列に分ける

実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。

出力例
['佐藤', '158.2', '50.1', '72']
ヒントを見る

カンマで区切られた部分を順に列へ分けます。数値に見える部分も、分割直後はどの種類の値か考えてください。

演習の解説

名前、身長、体重、点数の4つの文字列へ分かれます。数値に見える部分も、この段階では文字列です。

虫食いCSVの1行を列に分ける

___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。

row = "佐藤,158.2,50.1,72".___(",")
print(row)
ヒントを見る

区切り文字が現れる場所で文字列を分けます。分かれた数値も、まだ文字列のままです。

虫食いの解説
row = "佐藤,158.2,50.1,72".split(",")
print(row)

空欄には split が入ります。名前、身長、体重、点数の4つの文字列へ分かれます。数値に見える部分も、この段階では文字列です。

CSVファイルを読み込む

まずは,CSVファイルを開いて,中身をそのまま画面に表示してみましょう. ファイルを読むには open(オープン)という関数を使います.

chapter-07_code_2.py
import csv

# ファイルを開いて1行ずつ読む
f = open("data/sample/sokutei.csv", encoding="utf-8")
reader = csv.reader(f)
for gyou in reader:
    print(gyou)
f.close()

実行すると,次のように表示されます.

実行結果の例
['namae', 'shinchou', 'taijuu', 'tensuu']
['佐藤', '158.2', '50.1', '72']
['鈴木', '162.5', '55.4', '88']
['高橋', '155.0', '48.7', '64']
['田中', '168.3', '60.2', '91']
['伊藤', '160.1', '52.0', '55']
['渡辺', '165.7', '58.6', '78']

1行ずつ見ていこう.

1行目

import csv は,CSVファイルを読み書きするための便利な道具 (モジュールという)を使えるようにする命令です. csv を使う前に,はじめに1回だけ書きます.

4行目

open("...") で,指定したファイルを開きます. encoding="utf-8" は「このファイルの文字は UTF-8 という方式で 書かれている」と伝える指定です.日本語が文字化けしないための おまじないだと思っておけば十分です.開いた結果は変数 f に 代入します.

5行目

csv.reader(f) は,開いたファイル f を 「1行ずつ,カンマで区切って読んでくれる係」に変えます.これを変数 reader に代入します.

6∼7行目

for(繰り返し)を使って,reader から 1行ずつ取り出し,変数 gyou(行)に代入して表示します.

8行目

f.close() で,使い終わったファイルを閉じる.

実行結果を見ると,各行が ['佐藤', '158.2', '50.1', '72'] のような リストになっています.第6章で学んだリストです.つまり csv.reader は,CSVの1行を「カンマで区切ってリストにしたもの」として 渡してくれるのです.gyou[0] が名前,gyou[1] が身長,…と, 添字で各列を取り出せます.

行をまるごと表示するのではなく,ほしい列だけを取り出してみましょう. 名前の列(0列目)と点数の列(3列目)だけを並べて表示します.

chapter-07_code_4.py
import csv

f = open("data/sample/sokutei.csv", encoding="utf-8")
reader = csv.reader(f)
for gyou in reader:
    # 0列目(名前)と3列目(点数)だけを取り出す
    print(gyou[0], gyou[3])
f.close()

実行すると,次のように表示されます.

実行結果の例
namae tensuu
佐藤 72
鈴木 88
高橋 64
田中 91
伊藤 55
渡辺 78

gyou は1行ぶんのリストなので,gyou[0] で先頭(名前), gyou[3] で4番目(点数)だけを取り出しています.print に カンマ「,」で2つ並べると,間に半角スペースをはさんで横に並べて表示されます. ただし,いちばん上の行はヘッダー(見出し)なので,namae tensuu と いう見出しまで表示されてしまっています.この見出しをデータと区別して とばす方法は,あとの節で学ぶ.

ファイルが見つからないと FileNotFoundError(ファイルが無い,という エラー)が出ます.多くの場合,原因はファイルの置き場所か 名前のつづりです.プログラムから見て data/sample/sokutei.csv の場所に,その名前のファイルが本当にあるか確認するとよいでしょう.パスや ファイル名は半角で,大文字・小文字も正確に書きます.

  • open("ファイル名", encoding="utf-8") でファイルを開きます.

  • csv.reader を使うと,各行が「カンマで区切ったリスト」になります.

  • for gyou in reader: で1行ずつ取り出して処理します.

  • 使い終わったら f.close() で閉じる.

CSVを1行ずつ読み出す

知識

csv.readerはCSVの各行を列のリストとして読みます。ここでは教材内の文字列をファイルと同じ読み口にして試します。

import csv
import io
text = "namae,tensuu\n佐藤,72\n鈴木,88\n"
for row in csv.reader(io.StringIO(text)):
    print(row)
そのまま演習CSVを1行ずつ読み出す

実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。

出力例
['namae', 'tensuu']
['佐藤', '72']
['鈴木', '88']
ヒントを見る

最初の見出し行と、続くデータ行を順に読みます。各行を読み出したときに、何列のリストになるかを予想してください。

演習の解説

最初は見出し、次は佐藤と72、次は鈴木と88の行を読みます。実ファイルではopenで得たファイルをreaderへ渡します。

虫食いCSVを1行ずつ読み出す

___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。

import csv
import io
text = "namae,tensuu\n佐藤,72\n鈴木,88\n"
for row in csv.___(io.StringIO(text)):
    print(row)
ヒントを見る

CSVの読み取り用の処理をモジュールから呼びます。最初の行と、その後のデータ行を区別して追ってください。

虫食いの解説
import csv
import io
text = "namae,tensuu\n佐藤,72\n鈴木,88\n"
for row in csv.reader(io.StringIO(text)):
    print(row)

空欄には reader が入ります。最初は見出し、次は佐藤と72、次は鈴木と88の行を読みます。実ファイルではopenで得たファイルをreaderへ渡します。

読んだ文字を数値に変換する

前の節で,各列の値を取り出せるようになりました.では,点数の合計を 計算してみましょう.素直に足し算してみる.

chapter-07_code_6.py
import csv

f = open("data/sample/sokutei.csv", encoding="utf-8")
reader = csv.reader(f)
for gyou in reader:
    print(gyou[3] + gyou[3])   # 点数を足してみる?
f.close()

ところが実行すると,次のようになってしまう.

実行結果の例
tensuutensuu
7272
8888
6464
9191
5555
7878

数の足し算になっていません.72 + 72 は 144 になってほしいのに, "72" と "72" がそのままくっついて "7272" に なっています.これは,CSVから読んだ値がすべて文字列だからです. 見た目が数字でも,ファイルから読んだ gyou[3] は数値の 72 では なく,文字としての "72" なのです.

数として計算するには,文字列を数値に変換する必要があります. 整数にするには int,小数にするには float を使います.

chapter-07_code_8.py
import csv

f = open("data/sample/sokutei.csv", encoding="utf-8")
reader = csv.reader(f)
next(reader)                       # ヘッダー行を読みとばす
for gyou in reader:
    tensuu = int(gyou[3])          # 文字列を整数に変換
    print(tensuu + tensuu)         # 今度は数として足せる
f.close()

実行すると,ちゃんと数の足し算になります.

実行結果の例
144
176
128
182
110
156

int(gyou[3]) で文字列 "72" を整数の 72 に変換したので, tensuu + tensuu が 144 になりました.なお,5行目の next(reader) は,いちばん上のヘッダー行を1行だけ先に読みとばす命令である (次の節でくわしく説明する).身長や体重のように小数を含む列は, int ではなく float(gyou[1]) のように float で 変換します.

実際に小数の列を変換してみましょう.身長(1列目)を float で 数値にし,2倍してみる.

chapter-07_code_10.py
import csv

f = open("data/sample/sokutei.csv", encoding="utf-8")
reader = csv.reader(f)
next(reader)                       # ヘッダー行を読みとばす
for gyou in reader:
    shinchou = float(gyou[1])      # 文字列を小数に変換
    print(shinchou * 2)            # 小数として計算できる
f.close()

実行すると,次のように小数の計算になります.

実行結果の例
316.4
325.0
310.0
336.6
320.2
331.4

float(gyou[1]) で文字列 "158.2" を小数の 158.2 に 変換したので,* 2(2倍)がちゃんと 316.4 になっています. もし int(gyou[1]) と書くと,"158.2" のように小数点を含む 文字を整数に変換しようとして ValueError になります.小数を含む 列には float,整数だけの列には int を使う,と覚えておくと よいでしょう.

CSVから読んだ値は,数字に見えても文字列です.計算する前に int か float で数値に変換するのを忘れがちです. 「足したのにくっついた」「エラーになった」ときは,まず 変換し忘れていないか確認するとよいでしょう.逆に,名前のような文字を int しようとすると ValueError(値が変,というエラー)が出ます. 変換するのは数値の列だけです.

  • CSVから読んだ値は,見た目が数字でもすべて文字列です.

  • 計算する前に int(...)(整数)や float(...)(小数)で 数値に変換します.

  • 文字列のまま + すると,足し算ではなく文字の連結になります.

点数の文字列を数値へ変える

知識

CSVから取り出した点数は文字列なので、足し算の前にintへ変換します。

row = ["佐藤", "72"]
tensuu = int(row[1])
print(tensuu + 1)
そのまま演習点数の文字列を数値へ変える

実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。

出力例
73
ヒントを見る

列を取り出した段階と、型を変換した段階を分けて追います。最後の計算に使う値が文字列か数値かを確認してください。

演習の解説

点数の列は文字列「72」です。整数72へ変えると1を足して73になります。

虫食い点数の文字列を数値へ変える

___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。

row = ["佐藤", "72"]
tensuu = ___(row[1])
print(tensuu + 1)
ヒントを見る

列を取り出しただけでは文字列です。小数ではない点数として計算できる型へ変換します。

虫食いの解説
row = ["佐藤", "72"]
tensuu = int(row[1])
print(tensuu + 1)

空欄には int が入ります。点数の列は文字列「72」です。整数72へ変えると1を足して73になります。

ヘッダー行をとばして列を取り出す

CSVのいちばん上はヘッダー行(見出し)なので,データとして計算に 混ぜたくありません.前の節で使った next(reader) を使うと, 先頭の1行だけを先に読みとばせる.

ここでは,全員の名前と点数だけを,見やすく取り出して表示してみましょう.

chapter-07_code_12.py
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列目は点数(数値に変換)
    print(namae, tensuu)
f.close()

実行結果は次のとおりです.

実行結果の例
佐藤 72
鈴木 88
高橋 64
田中 91
伊藤 55
渡辺 78

next(reader) でヘッダー行 ['namae', ...] を先に1回読み取り, for に進む前に消費しています.そのため,繰り返しの中ではデータ行だけが gyou に入ります.あとは gyou[0] で名前,gyou[3] で 点数を取り出しているだけです.添字は0から始まるので,4つの列は 左から順に gyou[0],gyou[1],gyou[2],gyou[3] であることに注意します.

ヘッダー行をとばし忘れると,繰り返しの最初で int("tensuu") の ように見出しの文字を数値に変換しようとしてエラーになります. ValueError が出たら,まず「ヘッダーをとばしたか?」を疑うとよいでしょう. また,列の数より大きい添字(この例では gyou[4])を書くと IndexError(添字が範囲外)になります.

  • next(reader) で先頭のヘッダー行を1行だけ読みとばせる.

  • 各列は gyou[0], gyou[1], …と添字で取り出す (添字は0から).

  • 数値の列は,取り出すと同時に int や float で変換します.

見出しを除いてデータを読む

知識

ヘッダーはデータと同じ形の行ですが、点数ではありません。最初の行を飛ばしてからデータ列を扱います。

rows = [["namae", "tensuu"], ["佐藤", "72"], ["鈴木", "88"]]
for row in rows[1:]:
    print(row[1])
そのまま演習見出しを除いてデータを読む

実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。

出力例
72
88
ヒントを見る

スライスで除かれる先頭行を確認してください。残った各行のどの列を表示するかを追います。

演習の解説

先頭の見出しを除き、72と88をそれぞれ表示します。「tensuu」を整数へ変換しようとしないようにヘッダーを除く必要があります。

虫食い見出しを除いてデータを読む

___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。

rows = [["namae", "tensuu"], ["佐藤", "72"], ["鈴木", "88"]]
for row in rows[___]:
    print(row[1])
ヒントを見る

先頭の見出しはデータに含めません。2行目から最後まで取り出す範囲を考えてください。

虫食いの解説
rows = [["namae", "tensuu"], ["佐藤", "72"], ["鈴木", "88"]]
for row in rows[1:]:
    print(row[1])

空欄には 1: が入ります。先頭の見出しを除き、72と88をそれぞれ表示します。「tensuu」を整数へ変換しようとしないようにヘッダーを除く必要があります。

合計と平均を集計する

列の取り出しと数値変換ができれば,集計は簡単です. 合計を入れる変数を0から始めて,繰り返しの中で点数を足していこう.

chapter-07_code_14.py
import csv

f = open("data/sample/sokutei.csv", encoding="utf-8")
reader = csv.reader(f)
next(reader)                       # ヘッダーをとばす
goukei = 0                         # 合計を入れる箱(0から)
ninzuu = 0                         # 人数を数える箱
for gyou in reader:
    goukei = goukei + int(gyou[3]) # 点数を合計に足す
    ninzuu = ninzuu + 1            # 1人ぶん数える
f.close()
heikin = goukei / ninzuu           # 平均=合計÷人数
print("合計", goukei)
print("平均", heikin)

実行結果は次のとおりです.

実行結果の例
合計 448
平均 74.66666666666667

繰り返しの中で,goukei(合計)に各人の点数を足しながら,同時に ninzuu(人数)を1ずつ増やしています.すべての行を読み終えたあと, heikin = goukei / ninzuu で平均を計算しています. 合計を入れる goukei は,繰り返しの前に 0 にして おくことが大切です.これを初期化といいます.

goukei = 0 や ninzuu = 0 を繰り返しの中に書いて しまうと,1行読むたびに合計が0に戻ってしまい,正しく足し算できません. 初期化は必ず繰り返しの前に1回だけ書きます.

平均は 74.66666666666667 のように長い小数になることがあります. 小数点以下を1桁にそろえて表示したいときは,第3章で学んだ丸めや書式を 使います.たとえば round(heikin, 1) とすると 74.7 のように 四捨五入できます.

  • 合計用の変数を,繰り返しの前に 0 で初期化します.

  • 繰り返しの中で値を足し,人数を1ずつ数える.

  • 平均は「合計 ÷ 人数」で求めます.

合計と人数から平均を求める

知識

平均には合計と件数が必要です。点数を足しながら数え、最後に合計を件数で割ります。

tensuu_list = [72, 88, 64]
goukei = 0
ninzuu = 0
for t in tensuu_list:
    goukei = goukei + t
    ninzuu = ninzuu + 1
print(goukei / ninzuu)
そのまま演習合計と人数から平均を求める

実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。

出力例
74.66666666666667
ヒントを見る

点数の合計とデータの件数を、各回で別々に更新します。最後の割り算で使う分母と分子を確認してください。

演習の解説

合計は224、人数は3なので224÷3を表示します。人数0の場合には割り算できないため、実データでは空データへの対処も必要です。

虫食い合計と人数から平均を求める

___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。

tensuu_list = [72, 88, 64]
goukei = 0
ninzuu = 0
for t in tensuu_list:
    goukei = goukei + t
    ninzuu = ninzuu + 1
print(goukei ___ ninzuu)
ヒントを見る

合計を人数ごとに均等に分ける計算を使います。件数の加算と、最後の平均計算は別の段階です。

虫食いの解説
tensuu_list = [72, 88, 64]
goukei = 0
ninzuu = 0
for t in tensuu_list:
    goukei = goukei + t
    ninzuu = ninzuu + 1
print(goukei / ninzuu)

空欄には / が入ります。合計は224、人数は3なので224÷3を表示します。人数0の場合には割り算できないため、実データでは空データへの対処も必要です。

最大・最小を求める

合計や平均と同じくらいよく使うのが,「いちばん大きい値(最大)」 「いちばん小さい値(最小)」を求める集計です.たとえば テストの最高点や,気温のいちばん高かった日などです.

考え方は,これまで見た中でいちばん大きい値を,変数に覚えておくという ものです.新しい点数を読むたびに「今までの最大より大きいか?」を調べ, 大きければその値で覚えなおす.最高点を求めてみましょう.

chapter-07_code_16.py
import csv

f = open("data/sample/sokutei.csv", encoding="utf-8")
reader = csv.reader(f)
next(reader)                       # ヘッダーをとばす
saidai = 0                         # 最大を覚える箱(0から)
for gyou in reader:
    tensuu = int(gyou[3])          # 点数を数値にする
    if tensuu > saidai:            # 今までの最大より大きいなら
        saidai = tensuu            # その点数で覚えなおす
f.close()
print("最高点は", saidai, "点")

実行結果は次のとおりです.

実行結果の例
最高点は 91 点

繰り返しの中で,1人ずつ点数を取り出し,if tensuu > saidai: で 「今まで覚えている最大より大きいか」を判定しています.大きければ saidai をその点数で更新します.すべての行を読み終えたとき, saidai には全員の中でいちばん高い点数(91点)が残っています.

最小を求めるときは,saishou を 0 で初期化しては いけません.点数はふつう0より大きいので,「0より小さい値」が出てこず, 最小がいつまでも 0 のままになってしまう.最小を求めるときは, saishou = 100 のようにじゅうぶん大きい値から始め, if tensuu < saishou: で小さいほうへ更新していく.

  • 最大・最小は「これまでで最大(最小)の値を変数に覚えておく」考え方で求めます.

  • 読むたびに,今の値と覚えている値を比べ,必要なら更新します.

  • 最大は小さい値(0 など)から,最小は大きい値から始める.

データの上限と下限を調べる

知識

最大値と最小値は、比べる値を更新して探します。最初のデータを初期値にすると負の値でも扱えます。

tensuu = [72, 88, 64]
print(max(tensuu))
print(min(tensuu))
そのまま演習データの上限と下限を調べる

実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。

出力例
88
64
ヒントを見る

全データの大きい側と小さい側をそれぞれ探してください。2つの結果をどちらの順番で表示するかも確認します。

演習の解説

最大88、最小64を表示します。最大は大きい側、最小は小さい側なので、2つの関数の役割を区別します。

虫食いデータの上限と下限を調べる

___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。

tensuu = [72, 88, 64]
print(___(tensuu))
print(min(tensuu))
ヒントを見る

最初に求めたいのは一番大きな値です。小さな値を求める次の行と、関数の役割を区別してください。

虫食いの解説
tensuu = [72, 88, 64]
print(max(tensuu))
print(min(tensuu))

空欄には max が入ります。最大88、最小64を表示します。最大は大きい側、最小は小さい側なので、2つの関数の役割を区別します。

条件で絞って数える

集計では「ある条件にあてはまるものだけを数える」こともよくあります. たとえば「70点以上を合格とすると,合格者は何人か」を数えてみましょう. 第4章で学んだ条件分岐(if)を使います.

chapter-07_code_18.py
import csv

f = open("data/sample/sokutei.csv", encoding="utf-8")
reader = csv.reader(f)
next(reader)                       # ヘッダーをとばす
goukaku = 0                        # 合格者を数える箱
for gyou in reader:
    tensuu = int(gyou[3])          # 点数を数値にする
    if tensuu >= 70:               # 70点以上なら合格
        goukaku = goukaku + 1      # 1人ぶん数える
f.close()
print("合格者は", goukaku, "人")

実行結果は次のとおりです.

実行結果の例
合格者は 4 人

繰り返しの中で,1人ずつ点数を取り出し,if tensuu >= 70: で 「70点以上か」を判定しています.条件が成り立つ人だけ,goukaku(合格者) を1増やす.72・88・91・78の4人が70点以上なので,結果は4人です.

>= は「以上(より大きいか等しい)」を表す比較演算子 です.「未満」なら <,「ちょうど70点の人」を数えたいなら == 70 のように書きます.条件を変えるだけで,いろいろな絞り込みができます.

合格かどうかの判定に =(代入)を使ってはいけません.比べるときは 必ず == を2つ重ねる.if tensuu = 70: と書くとエラーに なります.= は代入,== は比較,という区別は,初学者が くり返しつまずく最重要ポイントです.

  • 数える用の変数を 0 で初期化し,条件に合うときだけ1増やす.

  • 絞り込みの判定には if と比較演算子(>=, <, == など)を使います.

  • 比較は ==,代入は =.混同しません.

合格点以上の人数を数える

知識

条件で絞って数えるときは、対象の全行を調べ、合格した行だけを件数に加えます。

tensuu = [72, 88, 64]
ninzuu = 0
for t in tensuu:
    if t >= 70:
        ninzuu = ninzuu + 1
print(ninzuu)
そのまま演習合格点以上の人数を数える

実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。

出力例
2
ヒントを見る

各点数が条件を満たすかを判定し、満たす回だけ人数を更新します。点数そのものの合計とは区別してください。

演習の解説

72と88の2人が70点以上です。64を数えないため、全員の人数3ではなく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)

空欄には >= が入ります。72と88の2人が70点以上です。64を数えないため、全員の人数3ではなく2を表示します。

別のCSVでも同じやり方で扱える

ここまで体力測定のCSV(sokutei.csv)を使ってきたが,CSVの扱い方は データの中身が変わってもまったく同じです.列の意味と添字さえ確認すれば, どんなデータにも同じ手順が使えます.例として,毎日の気温を記録した 別のCSVファイル data/sample/kion.csv を扱ってみましょう.中身は次のとおりで, 1列目が日付(何日目か),2列目がその日の気温です.

実行結果の例
hizuke,kion
1,28.5
2,31.2
3,30.0
4,27.8
5,33.1
6,29.4
7,32.6

気温は小数なので float で変換します.7日間の平均気温と, いちばん高かった気温(最高気温)を求めてみましょう.

chapter-07_code_21.py
import csv

f = open("data/sample/kion.csv", encoding="utf-8")
reader = csv.reader(f)
next(reader)                       # ヘッダーをとばす
goukei = 0                         # 気温の合計
ninzuu = 0                         # 日数を数える
saidai = 0                         # 最高気温を覚える
for gyou in reader:
    kion = float(gyou[1])          # 2列目の気温を小数に変換
    goukei = goukei + kion         # 合計に足す
    ninzuu = ninzuu + 1            # 1日ぶん数える
    if kion > saidai:              # 今までの最高より高ければ
        saidai = kion              # 覚えなおす
f.close()
heikin = round(goukei / ninzuu, 1) # 平均を小数1桁に丸める
print("平均気温", heikin)
print("最高気温", saidai)

実行結果は次のとおりです.

実行結果の例
平均気温 30.4
最高気温 33.1

やっていることは,前の節までと同じです.kion.csv は列が2つしか ないので,気温は gyou[1](2列目)で取り出します.あとは合計・日数・最高を 集めるだけで,体力測定のときとまったく同じ流れになっています.このように, ファイル名と列の添字を合わせるだけで,テストの点数でも,身長・体重でも, 気温でも,同じ作り方で集計できます.

別のCSVに切りかえたとき,列の数や順番を確認せずに前の添字を そのまま使うと,まちがった列を読んでしまう.sokutei.csv では点数が gyou[3] だったが,kion.csv では気温が gyou[1] です. 新しいファイルを使うときは,まずヘッダー行を見て,何列目に何があるかを 確かめるとよいでしょう.

  • CSVの扱い方は,データの中身が変わっても同じです.

  • ファイル名と,取り出す列の添字を,そのCSVに合わせるだけでよいでしょう.

  • 新しいCSVを使うときは,まずヘッダーで「何列目に何があるか」を確認します.

新しい列の並びを確認する

知識

CSVの列位置はファイルによって変わります。名前ではなく列番号で取り出す場合は、新しい見出しを確認します。

row = ["佐藤", "72", "158.2"]
tensuu = int(row[1])
print(tensuu)
そのまま演習新しい列の並びを確認する

実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。

出力例
72
ヒントを見る

新しい行の列を先頭から確認してください。点数を取り出す位置が、前のデータと同じかどうかを見直します。

演習の解説

この行では点数が2列目なので添字1を使います。元の測定データの4列目とは位置が異なり、そのまま添字3は使えません。

虫食い新しい列の並びを確認する

___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。

row = ["佐藤", "72", "___58.2"]
tensuu = int(row[1])
print(tensuu)
ヒントを見る

この行では、名前のすぐ次に点数があります。先頭の列から添字を数え直してください。

虫食いの解説
row = ["佐藤", "72", "158.2"]
tensuu = int(row[1])
print(tensuu)

空欄には 1 が入ります。この行では点数が2列目なので添字1を使います。元の測定データの4列目とは位置が異なり、そのまま添字3は使えません。

結果を整えて表示する

最後に,ここまで学んだことを組み合わせて,「全員の点数を一覧で出し, 最後に合計・平均・合格者数をまとめて表示する」プログラムを作ってみましょう. 読み込み・集計・出力の流れ(図7.1)がそのまま形になります.

chapter-07_code_23.py
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:
    namae = gyou[0]
    tensuu = int(gyou[3])
    print(namae, "さん:", tensuu, "点")
    goukei = goukei + tensuu       # 合計に足す
    ninzuu = ninzuu + 1            # 人数を数える
    if tensuu >= 70:               # 70点以上を合格
        goukaku = goukaku + 1
f.close()

ここまでで一覧の表示と集計が終わった.続けて,まとめを 表示します.

chapter-07_code_24.py
heikin = round(goukei / ninzuu, 1) # 平均を小数1桁に丸める
print("----------")
print("人数:", ninzuu, "人")
print("平均:", heikin, "点")
print("合格者:", goukaku, "人")

2つのプログラムを続けて実行すると,次のように表示されます.

実行結果の例
佐藤 さん: 72 点
鈴木 さん: 88 点
高橋 さん: 64 点
田中 さん: 91 点
伊藤 さん: 55 点
渡辺 さん: 78 点
----------
人数: 6 人
平均: 74.7 点
合格者: 4 人

繰り返しの中では,1人ずつ「名前さん:点数点」と一覧を表示しながら,同時に 合計・人数・合格者数を集めています.繰り返しが終わったあと,平均を round(..., 1) で小数第1位に丸め,区切り線とまとめを表示しています. print の中で文字列と数値をカンマ「,」で並べると,間に半角スペースを はさんで続けて表示されます.これだけで,読みやすい整形された結果に なりました.

このように,CSVファイルから読み込んだデータも,これまで学んだリスト・ 繰り返し・条件分岐・数値変換を組み合わせるだけで,自由に集計・整形できます. 身体測定の記録でも,テストの点数でも,毎日の気温の記録でも,列の意味と 添字を確認すれば,同じやり方で扱える.

  • CSV処理は「読み込む → 集計・整形する → 出力する」 の流れでできています.

  • 繰り返しの中で,一覧表示と集計(合計・人数・合格者数)を同時に行える.

  • round(値, 桁数) で小数の桁をそろえ,結果を見やすく整える.

  • リスト・繰り返し・条件分岐・数値変換の組み合わせで,表データを 自由に扱える.

集計結果に条件と単位を添える

知識

結果の説明と数値を同じ行へ表示すると、何を集計した結果かが分かります。単位も文字列として付けます。

ninzuu = 2
print("70点以上", ninzuu, "人")
そのまま演習集計結果に条件と単位を添える

実行前に、表示される行数と各行の値を予想してください。上のコードを編集欄へ開き、変更せずに実行します。その後「出力例」を開き、予想と実行結果を比べてください。入力操作はありません。各表示行の末尾には改行があります。

出力例
70点以上 2 人
ヒントを見る

説明、人数、単位が1つの表示命令へ渡されています。引数の間の空白と、最後の改行を含めて出力を予想します。

演習の解説

「70点以上 2 人」と半角空白で区切って表示します。人数だけの2より、条件と単位が読み手へ伝わります。

虫食い集計結果に条件と単位を添える

___の1か所だけを補い、上と同じ結果が出るコードにしてください。他の行は変えません。

___ = 2
print("70点以上", ninzuu, "人")
ヒントを見る

表示する値は、すでに準備した人数の変数から読み出します。説明や単位は文字列として別に渡します。

虫食いの解説
ninzuu = 2
print("70点以上", ninzuu, "人")

空欄には ninzuu が入ります。「70点以上 2 人」と半角空白で区切って表示します。人数だけの2より、条件と単位が読み手へ伝わります。

図で理解する

CSV 処理
CSV 処理
with とファイル
with とファイル

練習して確かめる

章末演習(10問)

ここには解答を載せていません。

  1. 章末演習章末演習 1

    CSV形式の成績データ DATA を csv.reader で1行ずつ取り出し,見出し行も含めたすべての行を,取り出したリストのまま表示します。

    入力

    キーボードからの入力はない(input() は使わない)。次の固定データを使います。

    DATA = 'bangou,namae,tensuu\n1,satou,72\n2,suzuki,91\n3,itou,55\n4,takahashi,68\n5,tanaka,85\n6,watanabe,77'
    

    1行目は見出し行(bangou,namae,tensuu),2行目以降は「番号,名前,点数」です。

    処理条件

    • 先頭に import csv と from io import StringIO を書き,csv.reader(StringIO(DATA)) で読み込みます。
    • 行の取り出しには for 文を使います。split による自前の分割,pandas などの外部ライブラリ,内包表記は使いません。
    • DATA の値は問題文のとおりに書く(境界値を確かめるときだけ一時的に書き換えてよい)。
    • 見出し行も読みとばさずに表示します。
    • 1回の繰り返しで1行分のリストを print にそのまま渡す。

    出力

    7行を表示します。各行はPythonがリストを表示するときの形そのままで,角かっこ [ ] で囲み,各要素を半角シングルクォート ' で囲み,要素の間は半角カンマと半角スペース1つ(,)で区切る。点数も文字列として '72' のように表示されます。すべて半角文字。上に示した行以外の表示(見出し,空行,説明文など)は出しません。

    実行例

    ['bangou', 'namae', 'tensuu']
    ['1', 'satou', '72']
    ['2', 'suzuki', '91']
    ['3', 'itou', '55']
    ['4', 'takahashi', '68']
    ['5', 'tanaka', '85']
    ['6', 'watanabe', '77']
    
    ヒントを見る

    まず `DATA` から読み取り用のオブジェクトを作り,次にそれを `for` 文で1行ずつ取り出します。取り出した1行がどんな型になっているかを,表示された角かっこやクォートから確かめましょう。

  2. 章末演習章末演習 2

    CSV形式の成績データ DATA から見出し行を読みとばし,各行の名前の列だけを1人1行で表示します。

    入力

    キーボードからの入力はない(input() は使わない)。次の固定データを使います。

    DATA = 'bangou,namae,tensuu\n1,satou,72\n2,suzuki,91\n3,itou,55\n4,takahashi,68'
    

    1行目は見出し行,2行目以降は「番号,名前,点数」です。

    処理条件

    • 先頭に import csv と from io import StringIO を書き,csv.reader(StringIO(DATA)) で読み込みます。
    • 行の取り出しには for 文を使います。split による自前の分割,pandas などの外部ライブラリ,内包表記は使いません。
    • DATA の値は問題文のとおりに書く(境界値を確かめるときだけ一時的に書き換えてよい)。
    • 見出し行は next(reader) を for 文の前に1回だけ書いて読みとばす。
    • 名前は1行分のリストから添字で取り出す(添字は0から数える)。

    出力

    名前だけを半角英小文字で1行に1人ずつ,データの順に表示します。番号や点数,見出しの namae は表示しません。上に示した行以外の表示(見出し,空行,説明文など)は出しません。

    境界値:DATA が見出し行だけ('bangou,namae,tensuu')のときは何も表示せず,エラーも出さずに終わります。

    実行例

    satou
    suzuki
    itou
    takahashi
    
    ヒントを見る

    見出し行を読みとばす処理は,繰り返しの中ではなく繰り返しが始まる前に置きます。次に,1行分のリストで名前が左から何番目にあるかを数え,添字が0から始まることに注意して取り出しましょう。

  3. 章末演習章末演習 3

    CSV形式の成績データ DATA の見出し行を next(reader) の戻り値として受け取り,その2列目と3列目の見出し名を1行目に表示します。続けて,各行の名前と点数を1人1行で表示します。

    入力

    キーボードからの入力はない(input() は使わない)。次の固定データを使います。

    DATA = 'bangou,namae,tensuu\n1,satou,72\n2,suzuki,91\n3,itou,55\n4,takahashi,68\n5,tanaka,85\n6,watanabe,77'
    

    1行目は見出し行,2行目以降は「番号,名前,点数」です。

    処理条件

    • 先頭に import csv と from io import StringIO を書き,csv.reader(StringIO(DATA)) で読み込みます。
    • 行の取り出しには for 文を使います。split による自前の分割,pandas などの外部ライブラリ,内包表記は使いません。
    • DATA の値は問題文のとおりに書く(境界値を確かめるときだけ一時的に書き換えてよい)。
    • next(reader) の戻り値(見出し行のリスト)を変数に代入し,1行目の表示にはその変数の要素を使います。'namae' や 'tensuu' という文字列をプログラムに直接書きません。
    • 2つの値は print にカンマで区切って渡す。

    出力

    1行目に見出し名2つ,2行目以降に名前と点数を,それぞれ半角スペース1つで区切って表示する(合計7行)。すべて半角文字。上に示した行以外の表示(見出し,空行,説明文など)は出しません。

    実行例

    namae tensuu
    satou 72
    suzuki 91
    itou 55
    takahashi 68
    tanaka 85
    watanabe 77
    
    ヒントを見る

    `next(reader)` は1行を読みとばすだけでなく,その1行をリストとして返します。まず見出し行を受け取って表示し,そのあと残りの行を繰り返しで処理するという順に組み立てましょう。

  4. 章末演習章末演習 4

    CSV形式の成績データ DATA から見出し行を読みとばし,全員の点数の合計と人数を求めて表示します。

    入力

    キーボードからの入力はない(input() は使わない)。次の固定データを使います。

    DATA = 'bangou,namae,tensuu\n1,satou,72\n2,suzuki,91\n3,itou,55\n4,takahashi,68\n5,tanaka,85\n6,watanabe,77'
    

    1行目は見出し行,2行目以降は「番号,名前,点数」で,点数は0〜100の整数です。

    処理条件

    • 先頭に import csv と from io import StringIO を書き,csv.reader(StringIO(DATA)) で読み込みます。
    • 行の取り出しには for 文を使います。split による自前の分割,pandas などの外部ライブラリ,内包表記は使いません。
    • DATA の値は問題文のとおりに書く(境界値を確かめるときだけ一時的に書き換えてよい)。
    • 見出し行は next(reader) で読みとばす。
    • 点数は int() で整数に変換します。
    • 合計と人数は,繰り返しの前に用意した変数へ繰り返しの中で累積して求めます。sum(),len(),list() は使いません。

    出力

    1行目に 合計,2行目に 人数 と表示し,それぞれ半角スペース1つのあとに半角数字の値を続ける(合計2行)。「人」などの単位は付けません。上に示した行以外の表示(見出し,空行,説明文など)は出しません。

    境界値:DATA が見出し行だけのときは 合計 0 と 人数 0 の2行を表示します。

    実行例

    合計 448
    人数 6
    
    ヒントを見る

    合計用と人数用の2つの変数を,それぞれ何から始めればよいかを最初に決めます。次に,1行読むたびに各変数がどう変わるかを考えます。CSVから読んだ値がどの型になっているかにも注意しましょう。

  5. 章末演習章末演習 5

    CSV形式の成績データ DATA から全員の点数の平均を求め,小数第1位に丸めて表示します。データが1件もないときは,割り算をせずにその旨を表示します。

    入力

    キーボードからの入力はない(input() は使わない)。次の固定データを使います。

    DATA = 'bangou,namae,tensuu\n1,satou,72\n2,suzuki,91\n3,itou,55\n4,takahashi,68\n5,tanaka,85\n6,watanabe,77'
    

    1行目は見出し行,2行目以降は「番号,名前,点数」で,点数は0〜100の整数です。

    処理条件

    • 先頭に import csv と from io import StringIO を書き,csv.reader(StringIO(DATA)) で読み込みます。
    • 行の取り出しには for 文を使います。split による自前の分割,pandas などの外部ライブラリ,内包表記は使いません。
    • DATA の値は問題文のとおりに書く(境界値を確かめるときだけ一時的に書き換えてよい)。
    • 見出し行は next(reader) で読みとばす。
    • 合計と人数は繰り返しの中で変数に累積して求めます。sum(),len(),list(),statistics モジュールは使いません。
    • 平均は合計÷人数で求め,round(平均, 1) で小数第1位に丸める。
    • 人数が0のときは割り算をせず,if で分けて表示を変えます。

    出力

    平均,半角スペース1つ,丸めた平均値(半角数字)を1行で表示します。平均がちょうど整数になる場合も 75.0 のように小数第1位まで表示されるが,それでよいでしょう。上に示した行以外の表示(見出し,空行,説明文など)は出しません。

    境界値:DATA が見出し行だけのときは データなし の1行だけを表示し,エラーを出しません。

    実行例

    平均 74.7
    
    ヒントを見る

    平均を出すのは,全員分を読み終えて合計と人数がそろったあとです。そのうえで,人数が0のまま割り算をするとどうなるかを考え,割り算の前に分かれ道を置きましょう。見出し行だけの `DATA` に書き換えて,その分かれ道が働くかも確かめましょう。

  6. 章末演習章末演習 6

    CSV形式の成績データ DATA から,全員の点数の最高点を求めて表示します。

    入力

    キーボードからの入力はない(input() は使わない)。次の固定データを使います。

    DATA = 'bangou,namae,tensuu\n1,satou,72\n2,suzuki,91\n3,itou,55\n4,tanaka,68\n5,watanabe,85\n6,takahashi,77'
    

    1行目は見出し行,2行目以降は「番号,名前,点数」で,点数は0〜100の整数です。

    処理条件

    • 先頭に import csv と from io import StringIO を書き,csv.reader(StringIO(DATA)) で読み込みます。
    • 行の取り出しには for 文を使います。split による自前の分割,pandas などの外部ライブラリ,内包表記は使いません。
    • DATA の値は問題文のとおりに書く(境界値を確かめるときだけ一時的に書き換えてよい)。
    • 見出し行は next(reader) で読みとばす。
    • 最高点は,繰り返しの中で if を使い,それまでの最高点より大きい点数が来たら覚えなおす方法で求めます。max(),sorted(),sort(),list() は使いません。
    • 点数は比べる前に int() で整数に変換します。

    出力

    最高点,半角スペース1つ,最高点(半角数字)を1行で表示します。上に示した行以外の表示(見出し,空行,説明文など)は出しません。

    境界値:全員が0点のデータでも 最高点 0 と表示します。

    実行例

    最高点 91
    
    ヒントを見る

    最初に「それまでの最高点」を入れておく変数の初期値を決めます。点数がとりうる範囲を考え,最初の1人を読んだときに必ず覚えなおしが起こる値を選びましょう。文字列のまま比べると数の大小にならないことにも注意します。

  7. 章末演習章末演習 7

    CSV形式の成績データ DATA から,最低点とその点数をとった人の名前を求めて表示します。最低点の人が複数いるときは,データの中で先に出てくる人の名前を表示します。

    入力

    キーボードからの入力はない(input() は使わない)。次の固定データを使います。

    DATA = 'bangou,namae,tensuu\n1,佐藤,72\n2,鈴木,91\n3,伊藤,55\n4,高橋,68\n5,田中,55\n6,渡辺,77'
    

    1行目は見出し行,2行目以降は「番号,名前,点数」で,名前は全角の漢字,点数は0〜100の整数です。

    処理条件

    • 先頭に import csv と from io import StringIO を書き,csv.reader(StringIO(DATA)) で読み込みます。
    • 行の取り出しには for 文を使います。split による自前の分割,pandas などの外部ライブラリ,内包表記は使いません。
    • DATA の値は問題文のとおりに書く(境界値を確かめるときだけ一時的に書き換えてよい)。
    • 見出し行は next(reader) で読みとばす。
    • 最低点と名前は,繰り返しの中で if を使って同時に覚えなおす方法で求めます。min(),sorted(),sort(),list() は使いません。
    • 点数は比べる前に int() で整数に変換します。

    出力

    1行目に 最低点,半角スペース1つ,最低点(半角数字)。2行目に 名前,半角スペース1つ,名前(データのとおりの全角漢字)。合計2行。上に示した行以外の表示(見出し,空行,説明文など)は出しません。

    実行例

    最低点 55
    名前 伊藤
    
    ヒントを見る

    最低点を覚える変数の初期値は,最初の1人で必ず覚えなおしが起こる値にします。次に,覚えなおすときに点数と名前を一緒に更新します。同じ点数が後から来たときに覚えなおすかどうかは,比較演算子に等号を含めるかどうかで決まります。

  8. 章末演習章末演習 8

    CSV形式の成績データ DATA から,点数が70点以上(ちょうど70点を含む)の人の名前を順に表示し,最後にその人数を表示します。

    入力

    キーボードからの入力はない(input() は使わない)。次の固定データを使います。

    DATA = 'bangou,namae,tensuu\n1,satou,72\n2,suzuki,91\n3,itou,55\n4,takahashi,70\n5,tanaka,85\n6,watanabe,69'
    

    1行目は見出し行,2行目以降は「番号,名前,点数」で,点数は0〜100の整数です。

    処理条件

    • 先頭に import csv と from io import StringIO を書き,csv.reader(StringIO(DATA)) で読み込みます。
    • 行の取り出しには for 文を使います。split による自前の分割,pandas などの外部ライブラリ,内包表記は使いません。
    • DATA の値は問題文のとおりに書く(境界値を確かめるときだけ一時的に書き換えてよい)。
    • 見出し行は next(reader) で読みとばす。
    • 条件の判定は if で行い,人数は繰り返しの中で変数に数えあげる。len(),list(),sum() は使いません。
    • 点数は比べる前に int() で整数に変換します。

    出力

    70点以上の人の名前(半角英小文字)を,データの順に1行に1人ずつ表示します。最後の行に 70点以上,半角スペース1つ,人数(半角数字),半角スペース1つ,人 を表示します。上に示した行以外の表示(見出し,空行,説明文など)は出しません。

    境界値:70点の人は名前を表示して数に入れ,69点の人は入れません。該当者がいないときは名前を表示せず,70点以上 0 人 の1行だけを表示します。

    実行例

    satou
    suzuki
    takahashi
    tanaka
    70点以上 4 人
    
    ヒントを見る

    条件に合う人だけで行う処理が2つ(名前の表示と数えあげ)あることを確かめ,どちらも条件の内側に置きます。人数の表示は全員を調べ終わってから1回だけ行います。「以上」がちょうど70点を含むことに合わせて比較演算子を選びましょう。

  9. 章末演習章末演習 9

    国語と数学の点数が入ったCSV形式のデータ DATA から,1人ずつ2科目の合計点を計算し,名前と合計点を表示します。

    入力

    キーボードからの入力はない(input() は使わない)。次の固定データを使います。

    DATA = 'bangou,namae,kokugo,suugaku\n1,satou,72,65\n2,suzuki,91,88\n3,itou,55,70\n4,takahashi,68,79'
    

    1行目は見出し行,2行目以降は「番号,名前,国語,数学」で,点数は0〜100の整数です。

    処理条件

    • 先頭に import csv と from io import StringIO を書き,csv.reader(StringIO(DATA)) で読み込みます。
    • 行の取り出しには for 文を使います。split による自前の分割,pandas などの外部ライブラリ,内包表記は使いません。
    • DATA の値は問題文のとおりに書く(境界値を確かめるときだけ一時的に書き換えてよい)。
    • 見出し行は next(reader) で読みとばす。
    • 国語と数学の値はそれぞれ int() で整数に変換してから + で足します。sum() は使いません。

    出力

    名前(半角英小文字)と2科目の合計点(半角数字)を半角スペース1つで区切り,データの順に1行に1人ずつ表示する(合計4行)。上に示した行以外の表示(見出し,空行,説明文など)は出しません。

    実行例

    satou 137
    suzuki 179
    itou 125
    takahashi 147
    
    ヒントを見る

    まず変換をせずに2つの列を `+` でつないで表示し,どんな結果になるかを観察してみましょう。そのうえで,足し算にするには何をしてから `+` を使えばよいかを考えます。

  10. 章末演習章末演習 10

    7日分の気温のCSVデータ DATA から,最高気温の平均,最高気温が最も高かった日とその値,最低気温が最も低かった日とその値を求めて表示します。

    入力

    キーボードからの入力はない(input() は使わない)。次の固定データを使います。

    DATA = 'hizuke,saikou,saitei\n7/1,29.5,24.1\n7/2,31.2,25.0\n7/3,33.1,26.2\n7/4,28.4,23.5\n7/5,30.0,24.8\n7/6,32.3,25.9\n7/7,28.3,23.0'
    

    1行目は見出し行,2行目以降は「日付,最高気温,最低気温」で,気温は小数第1位までの数(−50〜50)です。

    処理条件

    • 先頭に import csv と from io import StringIO を書き,csv.reader(StringIO(DATA)) で読み込みます。
    • 行の取り出しには for 文を使います。split による自前の分割,pandas などの外部ライブラリ,内包表記は使いません。
    • DATA の値は問題文のとおりに書く(境界値を確かめるときだけ一時的に書き換えてよい)。
    • 見出し行は next(reader) で読みとばす。
    • 気温は float() で数値に変換します。
    • 1回の繰り返しの中で,合計・日数の累積と,最大・最小の覚えなおし(if)をすべて行います。sum(),len(),max(),min(),sorted(),list(),statistics モジュールは使いません。
    • 平均は round(平均, 1) で小数第1位に丸める。
    • 同じ値の日が複数あるときは,先に出てくる日を表示します。

    出力

    次の3行を表示します。区切りはすべて半角スペース1つ,数字と日付は半角。

    1. 平均,丸めた最高気温の平均
    2. 最高,最高気温の最大値,その日付
    3. 最低,最低気温の最小値,その日付

    上に示した行以外の表示(見出し,空行,説明文など)は出しません。

    実行例

    平均 30.4
    最高 33.1 7/3
    最低 23.0 7/7
    
    ヒントを見る

    最初に,必要な変数(合計,日数,最大値とその日,最小値とその日)を書き出し,それぞれの初期値を気温の範囲から決めます。次に,1行ごとにどの列を使ってどの変数を更新するかを整理します。気温は小数なので,整数への変換ではうまくいきません。