質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

1回答

1146閲覧

numpyのデータ形状について

chem_search

総合スコア30

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2021/04/11 01:08

前提・実現したいこと

numpyのデータの形状について質問があります。
下記のコード内の3つのnp.arrayの違いについてです。

該当のソースコード

python

1 2import numpy as np 3import pandas as pd 4 5test1_array = np.array([0,1,2]) 6test2_array = np.array([[0],[1],[2]]) 7test3_array = np.array([[0,1,2]]) 8 9#DataFrame 10test1_df = pd.DataFrame(test1_array) 11test2_df = pd.DataFrame(test2_array) 12test3_df = pd.DataFrame(test3_array) 13 14#Series 15test1_Series = pd.Series(test1_array) 16test2_Series = pd.Series(test2_array) 17test3_Series = pd.Series(test3_array) 18 19#difference 20print(test1_array.ndim, test2_array.ndim, test3_array.ndim) 21print(test1_array.shape, test2_array.shape, test3_array.shape) 22

これら3つをDataFrameにすると、test1_arrayとtest2_arrayは
同じ3行1列のデータフレームができ、
test3_arrayは1行3列のデータフレームになります。

一方で、データフレームに変換したときはtest1_arrayとtest2_arrayは同じ表として表されるのに対し、
Seriesにするとtest1_arrayのみSeries化することができ、
test2_arrayとtest3_arrayは「Data must be 1-dimensional」とエラーが出ました。

test1_arrayは1次元、test2_array,test3_arrayは2次元であるのが
その理由というのは#differenceの部分のコードからわかったのですが、
この、1次元配列(shapeメソッドで(3,)と表示される)と、列数が1の2次元配列(shapeメソッドで(3,1)と表示される)
の違いがいまいちよくわかりません。
列数が1の2次元配列というのは、1次元配列と同じ意味にならないのでしょうか?

何か勘違いしている部分等ありましたら、ご指摘頂けますと嬉しいです。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jbpb0

2021/04/11 02:56 編集

> 列数が1の2次元配列というのは、1次元配列と同じ意味にならないのでしょうか? 質問のコードに追加して下記を実行して、結果を比べたら、同じではないことが分かると思います print(np.ones(3)) print(test1_array) print(test1_array * np.ones(3)) print(test2_array) print(test2_array * np.ones(3)) 質問の意味を勘違いしてたら、ごめんなさい
chem_search

2021/04/11 05:05

ご回答ありがとうございます。 回答頂いたコードで、たしかに計算結果は異なりました。 質問中の、test1_array, test2_array, test3_arrayの3つの状態がそれぞれ異なるというのが、 実際のプログラム上で異なる挙動をするというのは理解できたのですが、 感覚的にまだ腑に落ちていないんです。 行か列のどちらかの要素数が一つであるのにも関わらず、その配列が二次元であるということが混乱の原因だと思うのですが……。 あと、回答いただいたコードの結果から考えると、 2次元配列の時のshapeメソッドで表される(x, y)という形は x行y列の表に対応すると考えるのに対して、 1次元配列の時のshapeメソッドで表される(x, )という形は x行1列ではなく、1行x列の表に対応する、と考えればよいのでしょうか。
jbpb0

2021/04/11 07:37

> 1次元配列の時のshapeメソッドで表される(x, )という形は x行1列ではなく、1行x列の表に対応する、と考えればよいのでしょうか。 違うと思います 下記を実行してみてください A = np.array([[1,1], [2,2], [3,3]]) B = np.array([7, 8]) C = np.array([[7, 8]]) D = np.array([[7], [8]]) print(B.shape) print(C.shape) print(D.shape) print(A @ B) print(A @ C) print(A @ D) shapeが(2,)のBで計算できる式が、shapeが(1, 2)のCでは計算できず、shapeが(2, 1)のDでは計算できます また、Bでの計算結果と、Dでの計算結果は、数値の並びは違いますが、数値自体は等しいです したがって、この計算においては、shapeが(2,)のBにC, Dのどちらが近いか、あえて言うなら、shapeが(2, 1)のDの方が近い、となると思います (C, DどちらもBと同じではないですが、どちらが近いか無理やり決めたら、と言う話) そもそも、1次元配列と2次元配列は違うものだから、1次元配列は2次元配列のどれに対応するのか、と考えること自体が意味がないと思うのですが
chem_search

2021/04/11 07:59

何度も丁寧にご回答頂き、ありがとうございます。 参考リンクにもあるように、そもそも1次元配列と2次元配列は分けて考えたほうが良いということなのですね。 無理に全体を統一して考えようとしていたのが混乱の元でした。 分かりやすい例を色々と出して頂き、ありがとうございました!
guest

回答1

0

ベストアンサー

配列をDataFrameに変換した結果が同じであることに、引きずられてしまっていないでしょうか。
変換した結果が同じであることは、元のデータが同じであることを意味しません。

python

1>>> pd.DataFrame([0, 1, 2]) 2 0 30 0 41 1 52 2 6>>> pd.DataFrame({0: [0, 1, 2]}) 7 0 80 0 91 1 102 2 11>>> pd.DataFrame({0: {0: 0, 1: 1, 2: 2}}) 12 0 130 0 141 1 152 2

これらはすべて同じDataFrameを返していますが、そのことをもって[0, 1, 2]{0: [0, 1, 2]}{0: {0: 0, 1: 1, 2: 2}}は同じデータだと考えることはできません。

同様に、

python

1>>> pd.DataFrame(np.array([0, 1, 2])) 2 0 30 0 41 1 52 2 6>>> pd.DataFrame(np.array([[0], [1], [2]])) 7 0 80 0 91 1 102 2

この二つはどちらも同じDataFrameを返していますが、np.array([0, 1, 2])np.array([[0], [1], [2]])は同じものではありません。[0, 1, 2][[0], [1], [2]]も同じものではありません

1次元配列を元にDataFrameを作るとき、DataFrameは2次元のデータ構造なので、1次元配列は2次元のデータ構造に変換されます。

python

1>>> pd.DataFrame(np.array([0, 1, 2])) 2 0 30 0 41 1 52 2 6>>> pd.DataFrame(np.array([0, 1, 2])).values 7array([[0], 8 [1], 9 [2]]) 10>>> pd.DataFrame(np.array([0, 1, 2])).shape 11(3, 1)

このときnp.array([0, 1, 2]))が、(1, n) ではなく、(n, 1)の形でDateFrameに変換されるのは、1次元配列を読み込むときはそのように読み込むように、Pandasが作られているからです。「1次元配列は (n, 1) の2次元配列と同じ」だからそうなっているのではありません。

1次元配列と (1, n) の2次元配列がどう違うか、また1次元配列と (n, 1) の2次元配列がどう違うかが分からない、同じように思える、のでしたら、いちど下記のように配列から値を取り出す単純な操作をして、その違いを考えてみてはいかがでしょうか。
1次元配列から値を取り出すとその値はスカラー値で、それ以上の構造は持っていませんが、2次元配列から値を取り出すと、その値も配列で、さらにその配列から値を取り出すことができる、という違いがあります。

python

1>>> np.array([0, 1, 2]) 2array([0, 1, 2]) 3>>> np.array([0, 1, 2])[0] 40 5>>> np.array([0, 1, 2])[1] 61 7>>> np.array([0, 1, 2])[2] 82 9>>> np.array([0, 1, 2])[0][1] 10Traceback (most recent call last): 11 File "<stdin>", line 1, in <module> 12IndexError: invalid index to scalar variable.

python

1>>> np.array([[0], [1], [2]]) 2array([[0], 3 [1], 4 [2]]) 5>>> np.array([[0], [1], [2]])[0] 6array([0]) 7>>> np.array([[0], [1], [2]])[1] 8array([1]) 9>>> np.array([[0], [1], [2]])[2] 10array([2]) 11>>> np.array([[0], [1], [2]])[0][0] 120 13>>> np.array([[0], [1], [2]])[1][0] 141 15>>> np.array([[0], [1], [2]])[2][0] 162 17>>> np.array([[0], [1], [2]])[0][1] 18Traceback (most recent call last): 19 File "<stdin>", line 1, in <module> 20IndexError: index 1 is out of bounds for axis 0 with size 1

python

1>>> np.array([[0, 1, 2]]) 2array([[0, 1, 2]]) 3>>> np.array([[0, 1, 2]])[0] 4array([0, 1, 2]) 5>>> np.array([[0, 1, 2]])[1] 6Traceback (most recent call last): 7 File "<stdin>", line 1, in <module> 8IndexError: index 1 is out of bounds for axis 0 with size 1 9>>> np.array([[0, 1, 2]])[0][0] 100 11>>> np.array([[0, 1, 2]])[0][1] 121 13>>> np.array([[0, 1, 2]])[0][2] 142

もうひとついえば、np.array([0, 1, 2])のshapeの値が(3,)という表記なのは、shapeメソッドの返す値がPythonのtupleデータ型だからです。(n,)は値がひとつだけのtupleデータ型のリテラル表記です。本当だったらnp.array([0, 1, 2])のshapeが返す値は(3)という表記でもいいのです。(3,)という表記であることに意味はありません。

python

1>>> np.array([0, 1, 2]) 2array([0, 1, 2]) 3>>> np.array([0, 1, 2]).shape 4(3,) 5>>> type(np.array([0, 1, 2]).shape) 6<class 'tuple'>

投稿2021/04/11 11:57

etherbeg

総合スコア1195

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chem_search

2021/04/11 14:31

とても詳しく回答頂き、ありがとうございます! いろいろな例を出していただき、だいぶ頭が整理されてきました。 特に、 「このときnp.array([0, 1, 2]))が、(1, n) ではなく、(n, 1)の形でDateFrameに変換されるのは、1次元配列を読み込むときはそのように読み込むように、Pandasが作られているからです。「1次元配列は (n, 1) の2次元配列と同じ」だからそうなっているのではありません。 」 の説明でかなりすっきりしました。 無理に自分側でつじつまを合わせようとして混乱していました。 自分の中でしっかりと整理してみようと思います。
etherbeg

2021/04/11 15:18

「1次元配列を読み込むときはそのように読み込むように、Pandasが作られている」理由については、ちゃんと説明することができそうになかったので省略させていただきました。たぶんDataFrameのデータ構造が列志向(列方向にデータを持っている)だからだろうと推測しています。
ppaul

2021/04/11 15:19

本当だったらnp.array([0, 1, 2])のshapeが返す値は(3)という表記でもいいのです。(3,)という表記であることに意味はありません。に関してですが、 shapeの結果はTupleですので、(3,)でなければなりません。 https://docs.python.org/ja/3/library/stdtypes.html#sequence-types-list-tuple-range に書かれているように、 タプルを作るのはカンマであり、丸括弧ではありません。 なのです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問