業務自動化と機械学習に必須のリスト操作
Pythonを使った化学研究の自動化や、最近注目を集める機械学習による開発効率化において、コンテナ型(データをまとめて扱う型)の理解は欠かせません。
コンテナ型にはいくつか種類がありますが、特にリスト型は頻出中の頻出。
測定データをまとめたり、複数ファイルを処理したり、機械学習にデータを渡すときなど、さまざまな場面で活用されます。
本記事では、Pythonのコンテナ型の基本について、研究現場の実例を交えながら解説します!
本記事の内容は完璧にマスターしましょう!
基礎文法の全体像については以下の記事を参照ください。
研究者のPython活用で必要な8つのポイント はじめに 「プログラミングって難しそう…?」 そう思っている化学者研究者の皆さん、ちょっと待ってください! 化学者研究者がPythonを使いこなすために押さえておくべきポイントは8[…]
コンテナ型とは?
コンテナ型とは、複数のデータをひとまとめにできるデータ型です。
Pythonを学ぶときは最初に数値型や文字列型を学習しますが、これらは一つだけのデータです。
コンテナ型は複数のデータを集めて、一つの箱として扱う型です。
みんな大好きエクセルに例えると、数値型や文字列型の一つのデータをセルで扱い、コンテナ型では列全体のデータを扱う、というイメージです。
エクセルでも、A列データの平均を算出する、A列とB列のデータを使って関数計算した値をC列に記述、といった操作をよくしますよね。
Pythonのコンテナ型はこういった操作を可能にします。
主なコンテナ型
Pythonには主に以下の4種類のコンテナがあります:
型 | 特徴 | 例 |
リスト | 可変長、順序あり、変更可 | [1, 2, 3] |
タプル | 固定長、順序あり、変更不可 | (1, 2, 3) |
辞書 | キーと値のペア | {“Na”: 23, “Cl”: 35.5} |
集合 | ユニークな値の集まり | {1, 2, 3} |
各特徴について、以下に補足解説します。
- 可変長(リスト・辞書・集合)
コンテナ内の値(要素)をあとから追加・削除できます。測定データや実験条件が逐次追加されるような場面に向いています。
— - 固定長(タプル)
タプルは一度作成したら要素数を変更できません。リストと似ていますが、メモリ効率が良く処理速度が速いというメリットがあります。
— - 順序あり(リスト・タプル)
データの順番が保持されるため、インデックスでアクセスできます。時間軸データや機械学習の入力順などで重要です。
— - 変更可/不可
リストや辞書は要素を自由に編集できますがタプルは変更できません。
—
このように、それぞれの型が持つ性質を理解することで、目的に応じた使い分けが可能になります。
以降では、最も使用頻度の高いリスト型について詳しく見ていきましょう。
リスト型の基本
ここではリストの基本を解説します。
リストの作り方と、リスト内のデータ(=要素)へのアクセスの仕方をマスターしましょう。
下の図が頭に入れば完璧です!
リスト型の作り方
リストは、角カッコで囲って、各データをカンマで区切ることで定義できます。
各データのことを要素と呼びます。
それだけです。楽勝ですね。
以下サンプルコードです。
作ったリストの型をtype関数で確認しています。ちゃんとリスト型になっています。
list_a = [1.23, 2.0, 1.55, 1.4, 3.5, -0.98]
print(list_a)
# [1.23, 2.0, 1.55, 1.4, 3.5, -0.98]と出力
print(type(list_a))
# <class 'list'>と出力
インデックス
リストは複数データを取り扱うので、特定のデータにアクセスしたい状況が生まれます。
その時に使用するのがインデックスと呼ばれる住所です。
文字列のときに出てきたものと一緒です。
文字列操作をマスターして業務を自動化しよう! 化学研究者がPythonを活用する上で、とくに業務自動化のために「文字列操作」は重要です。 機械学習の活用にしか興味がない方は、大まかに理解しておく程度でも問題ないです。 業務を自動化[…]
インデックスで注意が必要なのは、0から始まるところ。
これさえ間違えなければ大丈夫です。
以下サンプルコードです。
先に作ったlist_aの特定の要素にアクセスしてみましょう。
print(list_a[0])
# 1.23と出力。0が一番左の要素。
print(list_a[3])
# 1.4と出力
スライス
インデックスを理解できたら、次はスライスです。
リストの中の特定の複数データにアクセスしたい時に使うのがスライスです。
「ここからここまでのデータが欲しい」、「ここからここまでで2つごとのデータが欲しい」、に応えるテクニックです。
スライスの使い方は上の図解の通りです。
コロンで区切って、始まり・終わりのインデックスと、データ間隔を指定してアクセスします。
注意が必要なのは、データの抜き出しは終わりのインデックスの1つ手前までということ。
また、データ間隔は指定した数”ごと”になります。
”おき”ではないので注意してください。
百聞は一見に如かず。以下サンプルコードです。
ここではインデックスとの対応が分かりやすいlist_bを作っています。
list_b = [0, 1, 2, 3, 4, 5]
print(list_b[2:5])
# インデックス2~4までにアクセス。[2, 3, 4]と出力
print(list_b[0:5:2])
# インデックス0~4まで2ごとにアクセス。[0, 2, 4]と出力
# インデックスを指定しなければ、「最初から」や「最後まで」という意味。
print(list_b[:3]) # list_b[0:3]と同義
print(list_b[3:]) # list_b[3:6]と同義
print(list_b[:]) # list_b[0:6]と同義
print(list_b[::2]) # list_b[0:6:2]と同義
print(list_b[2::2]) # list_b[2:6:2]と同義
最後にインデックスを指定しないテクニックを紹介しています。
始まり・終わりのインデックスは明示しなければ、暗黙的に「最初から」と「最後まで」を指定できます。
excel, csvファイルからのリスト作成
化学研究で扱う実験データは、csvやExcel形式で保存されていることがほとんどです。
Pythonでは、こうした外部ファイルのデータを読み込んで、コンテナ型として扱えます。
この操作にはpandasというライブラリを使用します。
pandasで外部ファイルを読み込むと「シリーズ」や「データフレーム」という型でデータを扱うことになります。
化学分野での機械学習の活用にはpandasは習得必須です。
なので別記事に詳細をまとめる予定です。
リストの操作
リスト型に対して何らかの処理(データを追加したい、データを並び替えたいなど)を行いたい時、「関数」や「メソッド」というものを使います。
下図のように、関数は処理対象のリストを引数にして、メソッドは処理対象のリストの後にピリオドをつけて記述します。
「関数」と「メソッド」混同されがちですが、これらの違いを理解しておくことは重要なので、別記事で詳説しています。
関数とは?メソッドとは? Pythonを学び始めると、「関数」と「メソッド」という用語が出てきます。 どちらも何らかの処理を施すものですが、「何が違うの?」「どう使い分けるの?」と疑問に思うことがあります。 例えば、リストを並び替えた[…]
関数やメソッドを使うとリストを自在に操作できます。
リストに対する操作は数多く存在しますが、その中でも使用頻度の高いものを厳選して解説します。
データの追加
データの追加には “append” や “extend”というメソッドを使います。
以下サンプルコードです。
“append”は単体のデータ、”extend”はリストで定義された複数データを追加できます。
list_c = [1, 2, 3]
# 単体データの追加
list_c.append(4)
print(list_c) # [1, 2, 3, 4]と出力
# 複数データの追加
list_d = [5, 6, 7]
list_c.extend(list_d)
print(list_c) # [1, 2, 3, 4, 5, 6, 7]と出力
データの削除
データの削除には “remove” や “clear”というメソッドを使います。
以下サンプルコードです。
“remove”は指定したデータ、”clear”はすべてのデータを削除できます。
list_e = [1, 2, 3]
# 指定したデータの削除
list_e.remove(2)
print(list_e) # [1, 3]と出力
# すべてのデータの削除
list_e.clear()
print(list_e) # []と出力
データ数の取得
リストの中にデータが何個あるかを知りたい時があります。
データ数を取得するには “len” という関数を使います。
以下サンプルコードです。
関数の結果(今回はデータ数)は変数で受け取ってあげる必要があります。
list_f = [1, 2, 3]
number = len(list_f)
print(number)
# リストのデータ数である「3」と出力
データの並び替え
データを昇順や降順で並び替えるには、関数を使う方法とメソッドを使う方法の2通りあります。
決定的な違いは、関数を使うと非破壊、メソッドを使うと破壊的というところです。
破壊的というのは、リストそのもののデータを変更してしまう、という意味で、つまり元のリストが失われてしまう方法です。
非破壊は元のリストが失われませんので、基本的には関数を使う方法を推奨します。
以下サンプルコードです。
破壊的、非破壊の差にも触れています。
# メソッドを使った破壊的ソート
list_g = [2, 1, 3, 5, 4]
list_g.sort()
print(list_g)
# 昇順ソートで[1, 2, 3, 4, 5]と出力され、元のlist_gは消失
# 関数を使った非破壊ソート
list_h = [2, 1, 3, 5, 4]
sort_list = sorted(list_h)
print(sort_list)
# 昇順ソートで[1, 2, 3, 4, 5]と出力
print(list_h)
# [2, 1, 3, 5, 4]と出力され、元のlist_hの保持を確認
# 降順にソート
re_sort_list = sorted(list_h, reverse=True)
print(re_sort_list)
# [5, 4, 3, 2, 1]と出力
# 逆順にソート
reverse_list = list(reversed(list_h))
print(reverse_list)
# [4, 5, 3, 1, 2]と出力
逆順にソートする “reversed” 関数については、戻り値がリストではありません。
そのため、list()関数を使ってリスト型に変換しています。
少し発展的な話ですが、これは関数の性質です。
このあたりの関数についての解説は別記事にまとめる予定です。
ループとの組み合わせで真価を発揮
ここがコンテナ型を学習するうえで一番重要な部分です。
複数データをコンテナ型で一つにまとめる最大のメリットは、複数データに対して同一の処理を高速で行えることです。
そして、同一の処理を施すにはループ(=繰り返し)が必要になります。
つまり、リストなどのコンテナ型は、forループと組み合わせることでその真価を発揮します。
ループ処理は別記事で詳しく解説予定ですが、コンテナ型の操作とループはセットで使われることが非常に多いことをぜひ意識しておきましょう。
その他のコンテナ型の概要
タプル
処理速度を追い求めたいとき、要素を変更しないことを保証したいときに使います。
要素の変更(追加や削除)ができないため、使用頻度は高くないです。
tuple_a = (1, 2, 3)
print(tuple_a) # (1, 2, 3)と出力
print(type(tuple_a)) # <class 'tuple'>と出力
辞書
キーと値がセットになっている、少し特殊なコンテナ型です。
値にラベル付けをしたいデータに用います。
リストの次に使用頻度が高いです。
サンプルコードでは原子名をキーに、原子量を値にしたデータを辞書型で表現しています。
element_dict = {"Na": 23, "Mg": 24.3, "Al": 27}
print(element_dict["Na"])
# キー "Na" に対応する値である "23"と出力
集合
重複を許さないコンテナ型です。こちらも使用頻度は低いです。
element_set = {"Na", "Mg", "Na"}
print(element_set)
# 重複している "Na" が削除されて{"Mg", "Na"}と出力
おわりに
コンテナ型は、Pythonによるデータ処理や機械学習の基本となる考え方です。
特にリスト型は、測定データ、実験条件、学習データなど、あらゆる研究データの整理と活用に欠かせません。
今後、ループ処理や内包表記、NumPy配列やPandasなどの応用に進んでいく際にも、コンテナ型の理解は土台となります。
ぜひ、日々の研究業務に取り入れて、データ処理や自動化、さらには機械学習まで一歩ずつステップアップしていきましょう。