はじめに
Pythonにおいて、リストやNumPy配列に要素を挿入する方法は多岐にわたります。この記事では、これらの方法を理解しやすいように、具体的な例を通じて説明してみます。
がこの記事の google colab へのリンクです。
使い方としては、
- リストは + でくっつけることができるが、numpy は配列同士の演算になるので、要素の結合にはならない。
- リストは可変長なので、同じリストに新しい要素を追加できるが、numpy の配列は固定長なので新しい numpy 配列に追加になる。
- リストはスライス
a[i:i]=b
のように、同じ場所を指定してそこに挿入ができるが、numpy だとできない。
初期データの設定
まず、操作に使用するリストとNumPy配列を定義します。
import numpy as np
a_list = [(1, 1), (2, 2), (3, 3)]
b_list = [(10, 10), (20, 20), (30, 30)]
a_np = np.array(a_list)
b_np = np.array(b_list)
ここでは、a_list
と b_list
という2つのリスト、およびこれらに相当するNumPy配列 a_np
と b_np
を作成しています。
リストへの挿入
スライスを使用する方法
a_slice = a_list.copy()
a_slice[1:1] = b_list
print("スライス:", a_slice)
# スライス: [(1, 1), (10, 10), (20, 20), (30, 30), (2, 2), (3, 3)]
スライスを使用する方法では、指定した位置に新しいリスト b_list
の要素を挿入します。ここでは、a_list
のインデックス1の位置に b_list
を挿入しています。
a_slice[1:1] = b_list
の 1:1
は、Pythonのスライス表記により、リスト a_slice
のインデックス1の直前(インデックス1の位置)に、リスト b_list
の要素を挿入することを指します。スライス表記 1:1
は、開始インデックスと終了インデックスが同じであるため、元のリストからは何も選択されません(つまり、空の範囲を示しています)。
具体的には、以下のように動作します:
-
a_slice[1:1]
は、リストa_slice
のインデックス1
の位置を指し、そこから何も選択しません(空のスライスを作成します)。 -
a_slice[1:1] = b_list
は、その空のスライスの位置にb_list
の要素を挿入します。
+ 演算子を使用する方法
a_plus = a_list[:1] + b_list + a_list[1:]
print("+ 演算子:", a_plus)
# + 演算子: [(1, 1), (10, 10), (20, 20), (30, 30), (2, 2), (3, 3)]
+ 演算子
を使用すると、リストを分割し、その間に別のリストを挿入することができます。この方法も、a_list
の指定された位置に b_list
を挿入しています。
insert を使う方法
a_insert = a_list.copy()
a_insert.insert(1, b_list)
print("insert:", a_insert)
# insert: [(1, 1), [(10, 10), (20, 20), (30, 30)], (2, 2), (3, 3)]
insert
メソッドを使用すると、リストの特定の位置に直接新しい要素を挿入できます。この例では、a_list
のインデックス1に b_list
を挿入しています。
NumPy配列への挿入
concatenate を使う
a_concat = np.concatenate((a_np[:1], b_np, a_np[1:]))
print("concatenate:", a_concat)
# concatenate:
#[[ 1 1]
# [10 10]
# [20 20]
# [30 30]
# [ 2 2]
# [ 3 3]]
NumPyの concatenate
関数を使うと、複数の配列を結合して新しい配列を作成できます。この例では、a_np
の指定された位置に b_np
を挿入しています。
numpy.insert を使う
a_insert = np.insert(a_np, 1, b_np, axis=0)
print("np.insert:", a_insert)
# np.insert:
#[[ 1 1]
# [10 10]
# [20 20]
# [30 30]
# [ 2 2]
# [ 3 3]]
NumPyの insert
関数を使うと、配列の特定の位置に新しい行または列を挿入できます。この例では、a_np
のインデックス1に b_np
の行を挿入しています。
サンプルコード全文
import numpy as np
# 初期データの設定
a_list = [(1, 1), (2, 2), (3, 3)]
b_list = [(10, 10), (20, 20), (30, 30)]
a_np = np.array(a_list)
b_np = np.array(b_list)
# 挿入位置
insert_index = 1
# リスト操作
def insert_into_list(a, b, index):
# スライスを使用する方法
a_slice = a.copy()
a_slice[index:index] = b
print("スライス:", a_slice)
# + 演算子を使用する方法
a_plus = a[:index] + b + a[index:]
print("+ 演算子:", a_plus)
# insert を使う方法
a_insert = a.copy()
a_insert.insert(index, b)
print("insert:", a_insert)
insert_into_list(a_list, b_list, insert_index)
# NumPy配列操作
def insert_into_numpy(a, b, index):
# concatenate を使う
a_concat = np.concatenate((a[:index], b, a[index:]))
print("concatenate:", a_concat)
# numpy.insert を使う
a_insert = np.insert(a, index, b, axis=0)
print("np.insert:", a_insert)
insert_into_numpy(a_np, b_np, insert_index)
これを実行すると、
スライス: [(1, 1), (10, 10), (20, 20), (30, 30), (2, 2), (3, 3)]
+ 演算子: [(1, 1), (10, 10), (20, 20), (30, 30), (2, 2), (3, 3)]
insert: [(1, 1), [(10, 10), (20, 20), (30, 30)], (2, 2), (3, 3)]
concatenate: [[ 1 1]
[10 10]
[20 20]
[30 30]
[ 2 2]
[ 3 3]]
np.insert: [[ 1 1]
[10 10]
[20 20]
[30 30]
[ 2 2]
[ 3 3]]
という出力になります。
その他のオペレーション
map関数を用いた掛け算
map関数を使うことで、関数にするほどのではない演算を短くかけます。list(map(
という使い方をすることで、map
で生成される要素を list
で強制的に配列の全要素に作用させることになります。具体例でみてみましょう。
一次元のリストの場合
my_list = [1, 2, 3, 4, 5]
factor = 2
multiplied_list = list(map(lambda x: x * factor, my_list))
# multiplied_list
# [2, 4, 6, 8, 10]
2次元のリストの場合
各タプルの第一要素に2を掛け、第二要素に3を掛けるとします。
以下のようにmap関数を使用できます。
my_list = [(1, 2), (3, 4), (5, 6)]
multiplied_list = list(map(lambda x: (x[0] * 2, x[1] * 3), my_list))
# multiplied_list
# [(2, 6), (6, 12), (10, 18)]
map関数の使い方の補足
map
関数は、指定された関数をリスト(または他のイテラブル)の各要素に適用し、結果をmapオブジェクト
として返します。mapオブジェクト
はイテレータであり、すべての結果を一度にメモリに格納するのではなく、要求されたときにそれぞれの結果を生成します。
list関数
をmap
の外側に使用する理由は、map
オブジェクトをリストに変換して、すべての結果を一度に取得するためです。list
を使用しない場合、mapオブジェクト
を直接イテレートするか、next関数を使用して各要素を個別に取り出す必要があります。
例えば、以下のように書くことができます:
# mapオブジェクトを直接使用
my_list = [(1, 2), (3, 4), (5, 6)]
multiplied_map = map(lambda x: (x[0] * 2, x[1] * 3), my_list)
# mapオブジェクトから要素を一つずつ取り出す
for item in multiplied_map:
print(item)
この方法は、すべての結果を一度にリストとして格納する必要がない場合に便利ですが、結果を再利用したい場合や、結果の全体像が必要な場合はlist関数を使用してリストに変換するのが良いでしょう。