本記事は,python入門講座シリーズの内容になります。その他の記事は,こちらの「Python入門講座/実践講座まとめ」をご覧ください。ターゲットは主にpythonを使ったことがない人向けで,簡潔で分かりやすい説明を心がけています。
読みたい場所へジャンプ!
今回のお題
数値データの入ったテキストファイルを読み込んでみよう!
ファイルを作ろう!
まず,下準備として2つのテキストファイルを作ります。メモ帳などを使ってOKです。それぞれ「test1.txt」「test2.txt」という名前を付けて,適当な場所に保存しましょう。
1 2 3 4
5 6 7 8
1 2
3 4
5 6
7 8
目標は,これらのファイルから数値を「整数型」としてリストに取り入れることです。これが,意外と厄介なので,ゆっくりと確認していきます。
結論
path1 = "test1.txt"
path2 = "test2.txt"
delimiter = " "
#テキストファイル(.txt)の行を数値として読み込む方法
num_row = 2
n_iter = 0
with open(path1) as f1:
data1 = [[0] for i in range(num_row)]
for l in f1.readlines():
data_row = [int(i) for i in l.strip().split(delimiter)]
data1[n_iter] = data_row
n_iter += 1
x1 = data1[0]
y1 = data1[1]
#テキストファイル(.txt)の列を数値として読み込む方法
with open(path2) as f2:
x2, y2 = [], []
for l in f2.readlines():
data2 = l.strip().split(delimiter)
x2 += [int(data2[0])]
y2 += [int(data2[1])]
data2 = [x2, y2]
となりますよね。ダイジョブです。1つずつ確認していきましょう。
解説
順を追って説明していきます。
colaboratoryにテキストファイルをアップロード
from google.colab import files
uploaded = files.upload()
こちらのコードを打ち込んで,先ほどのテキストファイル(”test1.txt”,”test2.txt”)の2つをアップロードしてください。
よく使う変数の設定
path1 = "test1.txt" #ファイル名
path2 = "test2.txt" #ファイル名
x1, y1 = [], [] #"test1.txt"の行
x2, y2 = [], [] #"test2.txt"の列
delimiter = " " #区切り文字の設定
pathというのは,ファイルが保存してある場所のことを指すのですが,今回はコードを記述している場所と同じところにテキストファイルをアップロードしたので,単なるファイル名でOKです。各ファイルのデータをしまっておくためのx, yも設定しておきます。
また,テキストファイルの区切り文字は半角スペースなので「” “」を設定しています。もし,テキストファイルの数値がタブで区切られている場合には「delimiter=”\t”」を利用してください。
基本的なファイル読み込みの流れ
f1 = open(path1)
data1 = f1.read()
print(data1)
f1.close()
pythonの組み込み関数でファイルを読み込む場合には,open関数を利用します。open関数はファイルオブジェクト(ファイルの操作ができる”モノ”)を返すので,f1という変数に代入します。これで,f1が“test1.txt”の内容を操作できる便利屋さんとして機能するようになりました。そこで,便利屋さんに「read()」という命令を与えます。これは,文字列をそのまま文字列として読み込む命令ですので,data1はtest1.txtに書かれている内容をそのまま表示します。
1 2 3 4
5 6 7 8
一点だけ補足なのですが,openしたオブジェクトをそのままにしておくと,pythonではファイルオブジェクトが開ける数が限られているため,エラーを起こしてしまう場合があります。そこで,ファイルオブジェクトにcloseしなくてはならない点に注意が必要です。
なんて方は,以下のwith構文を利用してください。with構文は「open()→close()」の流れ定められている設計図に使うことができる構文で,closeを省略できる優れものです。
with open(path1) as f1:
data1 = f1.read()
print(data1)
1 2 3 4
5 6 7 8
お疲れさまでした,これで終了です!……としたいところなのですが,コチラのdata1,実は文字列型なんです。
type(data1)
str
これでは,テキストファイルに書かれている数値を「整数型」として扱うことができません。具体的には,数値演算ができないのです。そこで,以下ではこちらの文字列を「1つ1つ分解して」「整数型に変換する」操作を解説していきます。
行ごとに分解
with open(path1) as f1:
data1 = f1.readlines()
print(data1)
['1 2 3 4\n', '5 6 7 8']
便利屋さんに「readlines()」と命令すれば,先ほどの文字列型のデータを「行ごとに」「リストとして」読み込みます。
「\n」は改行を表しています。テキストファイルを作った際も,4の後に改行をしませんでしたか?実際のテキストファイルも4の改行されていますので,パソコンは正直にテキストファイルの内容を出力してるのです。そこで,余分な「\n」を消去するために,リストの各要素(文字列)に対して「strip()」という命令をかけます。
with open(path1) as f1:
data1 = f1.readlines()
for l in range(len(data1)):
data1[l] = data1[l].strip()
print(data1)
['1 2 3 4', '5 6 7 8']
こうすることで,余分な「\n」が消えました。
要素を数字ごとに分解
今度は,要素を数字ごとに分解します。ここで,ようやく「delimiter」が登場します。文字列型の要素に「split()」という命令を与えることで,その文字列を「delimiter」ごとに分解してくれます。今回のテキストファイルは半角スペースで区切られていますので,半角スペースごとに要素を区切った文字列が出力されます。
with open(path1) as f1:
data1 = f1.readlines()
for l in range(len(data1)):
data1[l] = data1[l].strip().split(delimiter)
print(data1)
[['1', '2', '3', '4'], ['5', '6', '7', '8']]
整数値に変換
最後に,各要素を整数型に変換してx1, y1にしまっておきます。
with open(path1) as f1:
data1 = f1.readlines()
for l in range(len(data1)):
data1[l] = data1[l].strip().split(delimiter)
for m in range(len(data1[0])):
x1 += [int(data1[0][m])]
for n in range(len(data1[0])):
y1 += [int(data1[1][n])]
print(x1, y1)
[1, 2, 3, 4] [5, 6, 7, 8]
これにて,テキストファイルの数値をリストとして読み込むことができました!
もう少し簡単な方法
num_row = 2
n_iter = 0
with open(path1) as f1:
data1 = [[0] for i in range(num_row)]
for l in f1.readlines():
data_row = [int(i) for i in l.strip().split(delimiter)]
data1[n_iter] = data_row
n_iter += 1
x1 = data1[0]
y1 = data1[1]
print(x1)
print(y1)
print(data1)
f1という便利屋に「readlines()」という命令を与えたものを繰り返し構造(iterable)として利用します。何かしらの区切り(改行など)ごとに繰り返しを行いますが,基本的には行の数だけ繰り返すと考えればOKです。
列を読み込む場合
ここまでは,テキストファイルの行を読み込んでいましたが,テキストファイルの列を読み込む場合には下のようにします。
with open(path2) as f2:
x2, y2 = [], []
for l in f2.readlines():
data2 = l.strip().split(delimiter)
x2 += [int(data2[0])]
y2 += [int(data2[1])]
data2 = [x2, y2]
print(x2)
print(y2)
print(data2)
[1, 3, 5, 7]
[2, 4, 6, 8]
[[1, 3, 5, 7], [2, 4, 6, 8]]
本当にここで終了です!お疲れさまでした。