Pythonで2次元配列を定義する方法


724

次のように初期化された長さのない2次元配列を定義したい:

Matrix = [][]

しかし、それは動作しません...

私は以下のコードを試しましたが、それも間違っています:

Matrix = [5][5]

エラー:

Traceback ...

IndexError: list index out of range

私の間違いは何ですか?


14
配列などを定義していません。ただし、ここでの答えが示すように、多次元シーケンスを作成できます。Python 変数は型指定されていませんが、は強く型指定されています。
SingleNegationElimination 2011

1
よくわかりません。他の言語から来る:1D-Arrayを含む1D-Arrayと2D-Arrayの違いです。そして、私の知る限り、多次元配列(またはリスト)をPythonで持つ方法はありません。ここで言う必要があります...
19:48にDirk Reichel

回答:


1009

技術的には、初期化されていない配列にインデックスを付けようとしています。アイテムを追加する前に、まずリストで外部リストを初期化する必要があります。Pythonはこれを「リスト内包表記」と呼びます。

# Creates a list containing 5 lists, each of 8 items, all set to 0
w, h = 8, 5;
Matrix = [[0 for x in range(w)] for y in range(h)] 

これで、リストにアイテムを追加できます。

Matrix[0][0] = 1
Matrix[6][0] = 3 # error! range... 
Matrix[0][6] = 3 # valid

マトリックスは「y」アドレスメジャーであることに注意してください。つまり、「yインデックス」は「xインデックス」の前に来ます。

print Matrix[0][0] # prints 1
x, y = 0, 6 
print Matrix[x][y] # prints 3; be careful with indexing! 

好きなように名前を付けることができますが、内部リストと外部リストの両方に "x"を使用し、非正方行列が必要な場合に、インデックス付けで発生する可能性がある混乱を避けるために、このように見ています。


219
[[0 for x in range(cols_count)] for x for range(rows_count)]
songhir

3
ademar111190による奇妙な編集。Python 3にはxrangeはありませんが、Python 2を使用する必要がある場合、不要にオブジェクトを作成したくない場合は、xrangeを使用するのが適切です。
Dave

4
@daveあなたはゼロで埋め、それを必要といけない場合、使用することができrange、直接内部リストを作成するには:[range(5) for x in range(5)]
alanjds

2
@alanjds-それは本当ですが、それでもPython 2で外側の反復のために潜在的に多くの不要なオブジェクト参照を作成します(非常に大きな範囲でこれを試してください)。また、特定の値への初期化は、たいていの場合に必要です。これは、多くの場合0ではありません。rangeは反復可能なコレクションを生成します-xrangeはジェネレータを返します。私のポイントは、アデマーが実際には彼の修正よりもより一般的に正しく効率的なものを「修正」したということでした。
Dave

10
@ 6packkid [0] * wパーツはいいですが、[[0] * w] * h]予期しない動作が発生します。試してみてくださいmat = [[0] * 3] * 3; mat[0][1] = 10; print(mat == [[0, 10, 0], [0, 10, 0], [0, 10, 0]])mat = [[0] * 3 for i in range(3)]; mat[0][1] = 10; print(mat == [[0, 10, 0], [0, 0, 0], [0, 0, 0]])
センダール

407

マトリックスが本当に必要な場合は、を使用しnumpyた方がよいでしょう。numpyほとんどの場合、行列演算は2次元の配列型を使用します。新しい配列を作成するには多くの方法があります。最も便利なものの1つは、zeros形状パラメーターを取り、値をゼロに初期化して、指定された形状の配列を返す関数です。

>>> import numpy
>>> numpy.zeros((5, 5))
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.]])

2次元配列と行列を作成する他の方法をいくつか示します(コンパクトにするために出力を削除しています)。

numpy.arange(25).reshape((5, 5))         # create a 1-d range and reshape
numpy.array(range(25)).reshape((5, 5))   # pass a Python range and reshape
numpy.array([5] * 25).reshape((5, 5))    # pass a Python list and reshape
numpy.empty((5, 5))                      # allocate, but don't initialize
numpy.ones((5, 5))                       # initialize with ones

numpy提供していないmatrixにも種類を、それがされ、もはや推奨さのために任意の使用、およびから除去することができるnumpy将来に。


79
行列が必要なときはいつでも、numpyを使用します。この答えが最初でなければなりません。
Pat B

2
質問が英語の単語「マトリックス」を使用するという事実は、彼らがnp.matrixそれを表すために使用する必要があることを意味しません。numpyのマトリクスを表現する適切な方法はですarray
user2357112は、

@ user2357112、ご覧のとおり、上記の例のほとんどarrayは行列ではなくを出力します。常に推奨されるわけではありませんが、使用する正当な理由がありますmatrix-コンテキストが重要です。
センダーレ2017年

1
@senderle、使用する理由を拡張できますmatrixか?以来@オペレータが導入された、この記事が書かれていたので、1つの以下の理由があるように思われます。
2018

1
@jpp、以前の投稿で述べたように、Matlabから来た人はそれが便利だと思うかもしれません。しかし、numpyドキュメントは現在、クラスが非推奨になり、将来削除される可能性があることを示しているので、私はそれを答えから除外しました。
センデル

337

リストのリストを初期化するための短い表記は次のとおりです。

matrix = [[0]*5 for i in range(5)]

残念ながら、これをのようなものに短縮して5*[5*[0]]も、同じリストの5つのコピーが作成されるため、実際には機能しません。

>>> matrix = 5*[5*[0]]
>>> matrix
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
>>> matrix[4][4] = 2
>>> matrix
[[0, 0, 0, 0, 2], [0, 0, 0, 0, 2], [0, 0, 0, 0, 2], [0, 0, 0, 0, 2], [0, 0, 0, 0, 2]]

4
「短縮」の失敗の背後にある論理を説明できますか?この場合、pythonが同じリストのコピーを出力するのはなぜ[0]*5ですか?
mike622867

12
上記のコメントは正確には当てはまりません。[0] * 5は、番号0を表す同じオブジェクトへの参照を5回使用したシーケンスを作成します。 -または、プリミティブデータ型と考えるかもしれません-不変なので、コピーを作成する代わりに同じオブジェクトへの参照で問題が発生することはありません。)
dreua

4
より多くの神託:[[0]*5 for _ in range(5)]匿名のループカウンタを使用していない
ジャン=フランソワ・ファーブル

2番目の例で浅いコピーの問題を指摘できてうれしいです。
whatacold

@dreuaに感謝し[0]*5ます。どうすればうまく機能するか、本当に混乱しました。なぜ私[{0}]*8も悪い考えになるのか理解しました。
kuku

110

空の行列を作成する場合、正しい構文は次のとおりです。

matrix = [[]]

そして、0で満たされたサイズ5の行列を生成したい場合は、

matrix = [[0 for i in xrange(5)] for i in xrange(5)]

@KorayTugayマトリックスは、別のリスト(列)内にネストされたPythonリスト(行)を使用して表されるためです。
elig

2
Python-3の場合は、xrange funcの代わりに範囲関数を使用します
Rakesh Chaudhari

76

一部の要素を保持するための2次元のコンテナーが必要な場合は、代わりに辞書を使用すると便利です。

Matrix = {}

次に、次のことができます。

Matrix[1,2] = 15
print Matrix[1,2]

これ1,2はタプルなので機能し、辞書にインデックスを付けるためのキーとして使用しています。結果は、まばらな疎行列に似ています。

osaとJosap Vallsで示されているMatrix = collections.defaultdict(lambda:0)ように、欠落している要素のデフォルト値がになるように使用することもできます0

Vatsalはさらに、この方法は大きな行列ではおそらくあまり効率的ではなく、コードのパフォーマンスが重要でない部分でのみ使用する必要があることを指摘しています。


2
次にimport collections; Matrix = collections.defaultdict(float)、を実行して、初期化されていない要素をゼロに置き換えることもできます。
osa 2015年

2
キーとしてタプル(1,2)のdictにアクセスしないのは、O(n)の最悪の場合の複雑さです。内部的にはタプルをハッシュします。一方、2D配列を使用すると、O [1]インデックス[1,2]アクセスにアクセスする時間が複雑になります。したがって、これにdictを使用することは良い選択ではありません。
Vatsal、2015年

@Vatsal wiki.python.org/moin/TimeComplexityは、平均的なケースはO(1)であると述べていますが、あなたは最悪のケースについては正しいです。とにかく、あなたがたくさんのアイテムについて話しているのでなければ、あなたはこの違いを気にしないでしょう。実は、アクセス時間よりもメモリの方が気になります。
enobayram 2015年

また、アルゴリズムの全体的な複雑度がO(n ^ 2)以上になるまで、dictsの使用を避けようとします。「n」回のO(n)アクセスはO(n ^ 2)の複雑さを与えます。
Vatsal、2015年

@enobayram申し訳ありませんが、同意しません。最悪の場合のO(n)アクセスが 'n'回行われる場合、漸近分析は常にO(n ^ 2)を与えます。償却分析がより低い限界を与えることができるところ。そして、償却されたケースと平均的なケースの間には大きな違いがあります...仮定や曖昧なコメントを行う前に参照してください
Vatsal

42

Pythonでは、リストのリストを作成します。事前に寸法を宣言する必要はありませんが、宣言できます。例えば:

matrix = []
matrix.append([])
matrix.append([])
matrix[0].append(2)
matrix[1].append(3)

ここで、matrix [0] [0] == 2およびmatrix [1] [0] == 3です。リスト内包構文も使用できます。この例では、これを2回使用して「2次元リスト」を作成します。

from itertools import count, takewhile
matrix = [[i for i in takewhile(lambda j: j < (k+1) * 10, count(k*10))] for k in range(10)]

6
extend最初のケースでも役立ちます:で始める場合m = [[]]、を使用して内部リストに追加(行を拡張)しm[0].extend([1,2])、を使用して外部リストに追加(新しい行を追加)m.append([3,4])することができます[[1, 2], [3, 4]]。これらの操作では、をそのまま使用できます。
askewchan 2013年

22

受け入れられた答えは適切ですが、完全に空の配列を作成するためにも使用できることを理解するのにしばらく時間がかかりました。

l =  [[] for _ in range(3)]

結果は

[[], [], []]

22

リストのリストを作成する必要があります。最善の方法は、ネストされた内包表記を使用することです。

>>> matrix = [[0 for i in range(5)] for j in range(5)]
>>> pprint.pprint(matrix)
[[0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0]]

あなたの[5][5]例では、内部に整数「5」を含むリストを作成していて、その5番目の項目にアクセスしようとすると、5番目の項目がないため、当然IndexErrorが発生します。

>>> l = [5]
>>> l[5]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

実際ROW_INDEX(I '')とcolumn_index( 'J')についての配列は次の通りである: '>>>マトリックス= [0範囲内ROW_INDEXための範囲内column_index(5)](5)]'
Aniruddha Kalburgi

22
rows = int(input())
cols = int(input())

matrix = []
for i in range(rows):
  row = []
  for j in range(cols):
    row.append(0)
  matrix.append(row)

print(matrix)

なぜそんなに長いコードなのPythonですか?

Pythonに慣れていない昔、2Dマトリックスを書くための1行の答えを見て、Pythonで2Dマトリックスを再び使用するつもりはないと自分に言い聞かせました。(これらの単一行はかなり恐ろしく、Pythonが何をしているかについての情報を私に与えませんでした。また、私はこれらの省略形を知らないことに注意してください。)

とにかく、これはC、CPP、Javaのバックグラウンドから来た初心者のためのコードです

Pythonの愛好家とエキスパートへの注意:詳細なコードを書いたからといって、反対票を投じないでください。


13

読みやすくするための書き直し:

# 2D array/ matrix

# 5 rows, 5 cols
rows_count = 5
cols_count = 5

# create
#     creation looks reverse
#     create an array of "cols_count" cols, for each of the "rows_count" rows
#        all elements are initialized to 0
two_d_array = [[0 for j in range(cols_count)] for i in range(rows_count)]

# index is from 0 to 4
#     for both rows & cols
#     since 5 rows, 5 cols

# use
two_d_array[0][0] = 1
print two_d_array[0][0]  # prints 1   # 1st row, 1st col (top-left element of matrix)

two_d_array[1][0] = 2
print two_d_array[1][0]  # prints 2   # 2nd row, 1st col

two_d_array[1][4] = 3
print two_d_array[1][4]  # prints 3   # 2nd row, last col

two_d_array[4][4] = 4
print two_d_array[4][4]  # prints 4   # last row, last col (right, bottom element of matrix)

13

使用する:

matrix = [[0]*5 for i in range(5)]

このレベルではデータが不変であるため、最初のディメンションの* 5が機能します。


5
私はおそらくこれを次のように書くでしょうmatrix = [[0]*cols for _ in range(rows)]
Shital Shah

12

ゼロ(1)の行列を宣言するには:

numpy.zeros((x, y))

例えば

>>> numpy.zeros((3, 5))
    array([[ 0.,  0.,  0.,  0.,  0.],
   [ 0.,  0.,  0.,  0.,  0.],
   [ 0.,  0.,  0.,  0.,  0.]])

またはnumpy.ones((x、y))例

>>> np.ones((3, 5))
array([[ 1.,  1.,  1.,  1.,  1.],
   [ 1.,  1.,  1.,  1.,  1.],
   [ 1.,  1.,  1.,  1.,  1.]])

三次元でも可能です。(http://www.astro.ufl.edu/~warner/prog/python.html参照->多次元配列)


12

これは私が通常Pythonで2D配列を作成する方法です。

col = 3
row = 4
array = [[0] * col for _ in range(row)]

この構文は、リスト内包表記で2つのforループを使用するよりも覚えやすいと思います。


11

私は最初のPythonスクリプトを使用しています。正方行列の例に少し混乱したので、次の例が時間の節約に役立つことを願っています。

 # Creates a 2 x 5 matrix
 Matrix = [[0 for y in xrange(5)] for x in xrange(2)]

そのため

Matrix[1][4] = 2 # Valid
Matrix[4][1] = 3 # IndexError: list index out of range

10

NumPyを使用すると、次のように空の行列を初期化できます。

import numpy as np
mm = np.matrix([])

そして、後でこのようなデータを追加します:

mm = np.append(mm, [[1,2]], axis=1)

"リスト内包表記"ではなくnumpyを使用することの長所と短所は何でしょうか?
モニカの革命

7

私はこのようにコンマで区切られたファイルを読み込みます:

data=[]
for l in infile:
    l = split(',')
    data.append(l)

リスト「data」は、インデックスdata [row] [col]を含むリストのリストです。


7

リストのリストについて考えることを強いられるのではなく、2D配列として考えることができるようにしたい場合(私の意見でははるかに自然です)、次のことができます。

import numpy
Nx=3; Ny=4
my2Dlist= numpy.zeros((Nx,Ny)).tolist()

結果はリスト(NumPy配列ではない)であり、数値、文字列など、個々の位置を上書きできます。


あるnumpy.matrixと等価numpy.zerosリストされずにゼロを付けませんか?
モニカの革命

6

それが辞書の目的です!

matrix = {}

キーは次の2つの方法で定義できます。

matrix[0,0] = value

または

matrix = { (0,0)  : value }

結果:

   [ value,  value,  value,  value,  value],
   [ value,  value,  value,  value,  value],
   ...

6

使用する:

import copy

def ndlist(*args, init=0):
    dp = init
    for x in reversed(args):
        dp = [copy.deepcopy(dp) for _ in range(x)]
    return dp

l = ndlist(1,2,3,4) # 4 dimensional list initialized with 0's
l[0][1][2][3] = 1

私はNumPyが進むべき道だと思います。上記は、NumPyを使用したくない場合の一般的なものです。


私は、numpyを使用せずにバニラPythonで簡単なことをするこの試みが好きです。
リックヘンダーソン

4

リストを使用して:

matrix_in_python  = [['Roy',80,75,85,90,95],['John',75,80,75,85,100],['Dave',80,80,80,90,95]]

dictを使用して:この情報をハッシュテーブルに保存して、次のような高速検索を行うこともできます。

matrix = { '1':[0,0] , '2':[0,1],'3':[0,2],'4' : [1,0],'5':[1,1],'6':[1,2],'7':[2,0],'8':[2,1],'9':[2,2]};

matrix ['1']はO(1)時間の結果を与えます

* nb:ハッシュテーブルの衝突に対処する必要があります


4

開始前にサイズ情報がない場合は、2つの1次元リストを作成します。

list 1: To store rows
list 2: Actual two-dimensional matrix

行全体を最初のリストに格納します。完了したら、リスト1をリスト2に追加します。

from random import randint

coordinates=[]
temp=[]
points=int(raw_input("Enter No Of Coordinates >"))
for i in range(0,points):
    randomx=randint(0,1000)
    randomy=randint(0,1000)
    temp=[]
    temp.append(randomx)
    temp.append(randomy)
    coordinates.append(temp)

print coordinates

出力:

Enter No Of Coordinates >4
[[522, 96], [378, 276], [349, 741], [238, 439]]

3
# Creates a list containing 5 lists initialized to 0
Matrix = [[0]*5]*5

この短い表現に注意してください。@ FJの回答にある完全な説明を参照してください


19
このように注意してください。Matrix[0], Matrix[1], ..., Matrix[4]すべてが同じ配列を指すため、の後はMatrix[0][0] = 3、と予想されMatrix[0][0] == Matrix[1][0] == ... == Matrix[4][0] == 3ます。
gongzhitaao 2014

1
コメントをありがとうgongzhitaao。私がそれより前にそれを読んだとしたら、少なくとも30分は節約できたでしょう。各行がメモリ内の同じ場所を指すマトリックスを持っていることは、あまり役に立たないと思われます。それも危険です!これは、質問をしたMasoud Abasianがしたいことではないと確信しています。
エイドリアン

7
正解ではないため、この答えは削除してください。初心者は混乱するかもしれません。
cxxl 2016年

2
何の答えですか?「FJ」という名前のユーザーが表示されません(回答が削除されていても表示されません)。
Peter Mortensen

3
l=[[0]*(L) for _ in range(W)]

より高速になります:

l = [[0 for x in range(L)] for y in range(W)] 

2
以下ですでに回答されている回答の重複回答。また、どこでも使用されていないので、[[0]*(L) for i in range(W)]必要があります[[0]*(L) for _ in range(W)]i
Ayush Vatsyayan

2

次のように、角かっこで2つ以上の角かっこまたは3番目の角かっこ([]コンマで区切られた)を入れ子にして、空の2次元リストを作成できます。

Matrix = [[], []]

ここで、1を追加したい場合は、Matrix[0][0]次のように入力します。

Matrix[0].append(1)

次に、Matrixと入力してEnterキーを押します。出力は次のようになります。

[[1], []]


1

事前に定義された数値を持つマトリックスが必要な場合は、次のコードを使用できます。

def matrix(rows, cols, start=0):
    return [[c + start + r * cols for c in range(cols)] for r in range(rows)]


assert matrix(2, 3, 1) == [[1, 2, 3], [4, 5, 6]]

1

Pythonで行列を作成するためのコードスニペットを次に示します。

# get the input rows and cols
rows = int(input("rows : "))
cols = int(input("Cols : "))

# initialize the list
l=[[0]*cols for i in range(rows)]

# fill some random values in it
for i in range(0,rows):
    for j in range(0,cols):
        l[i][j] = i+j

# print the list
for i in range(0,rows):
    print()
    for j in range(0,cols):
        print(l[i][j],end=" ")

私が何かを見逃した場合は提案してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.