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

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

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

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

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Python

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

配列

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

Q&A

解決済

3回答

1738閲覧

[Python]行列を任意のエリアごとに計算し、サイズを縮小したい

sabakan4040

総合スコア5

NumPy

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

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Python

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

配列

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

0グッド

0クリップ

投稿2020/10/19 17:18

編集2020/10/21 14:39

前提・実現したいこと

Pythonで行列の要素を、エリアごとに合計して
新たに行列として計算したいです。
列数m、行数(m*n)、の行列が手元にあります。
行数をmで割って、新たに列数m、行数nの行列が欲しいのですが、
その際同じエリアにある要素の合計を求めたいです。

イメージ説明
元データの名前はsubSといいます。
今現在は理解のために2列、4行のデータを触っています。
(行数は必ず列数の整数倍になります。例に出したのが(9,3),(4,2)ですが、(12,3)などもあり得ます)

python3

1print(subS) 2[[4.0566930769471305 3.7447996916033945] 3 [4.993066255471194 5.408924102596176] 4 [9.46561717954331 8.737865947074592] 5 [7.489599383206791 8.113386153894263]] 6#subS.shape[1]#subSの列数=2 7#subS.shape[0]#subSの行数=4 8for k in range(subS.shape[1]): 9 k=np.split(subS,subS.shape[1],axis=1) 10 for h in range(int(subS.shape[0]/subS.shape[1])): 11 h=np.split(k,subS.shape[0]/subS.shape[1],axis=0) 12

###備考
自分は、上記のコードで、subSを列ごとに分解→さらに行数をm等分→各々和を出して→分解したものをくっつける
というやり方を試みましたが、知識不足かうまくいきません。
そもそも繰り返しの中で変数kに入れた行列が、次のhの繰り返しでうまくいかなかったりなど、、

今提示したやり方でなくとも、何か良い方法はありませんでしょうか。

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

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

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

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

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

guest

回答3

0

すでに解決済になっていますが、ベストアンサーとなっている解答の

python

1subS_splits = np.split(subS,col,axis=0)

という部分は誤っているのではないでしょうか。(12, 3)形の配列を入れると出力の形は(4, 3)ですよね?


また、方法としても.reshape()メソッドを用いたより簡単かつ高速な方法があります。
これによって(m*n, m)形の配列を(n, m, m)形の配列に変更することができ、真ん中の次元のm個を合計すれば目的の(n, m)形の配列になります。

python

1import numpy as np 2 3subS = np.array([[4.0566930769471305, 3.7447996916033945], 4 [4.993066255471194, 5.408924102596176], 5 [9.46561717954331, 8.737865947074592], 6 [7.489599383206791, 8.113386153894263]]) 7 8m = subS.shape[1] 9sums = subS.reshape(-1, m, m).sum(1) 10print(sums) 11# [[ 9.04975933 9.15372379] 12# [16.95521656 16.8512521 ]]

(12, 3)形の配列を例にします。
(3*4, 3)形の配列を(4, 3, 3)形の配列に変更後、真ん中の次元を合計して(4, 3)の形にしています。

python

1subS = np.arange(1, 37).reshape(3, 12).T 2print(subS) 3# [[ 1 13 25] 4# [ 2 14 26] 5# [ 3 15 27] 6# [ 4 16 28] 7# [ 5 17 29] 8# [ 6 18 30] 9# [ 7 19 31] 10# [ 8 20 32] 11# [ 9 21 33] 12# [10 22 34] 13# [11 23 35] 14# [12 24 36]] 15 16m = subS.shape[1] 17reshaped = subS.reshape(-1, m, m) 18print(reshaped) 19# [[[ 1 13 25] 20# [ 2 14 26] 21# [ 3 15 27]] 22# 23# [[ 4 16 28] 24# [ 5 17 29] 25# [ 6 18 30]] 26# 27# [[ 7 19 31] 28# [ 8 20 32] 29# [ 9 21 33]] 30# 31# [[10 22 34] 32# [11 23 35] 33# [12 24 36]]] 34 35sums = reshaped.sum(1) 36print(sums) 37# [[ 6 42 78] 38# [ 15 51 87] 39# [ 24 60 96] 40# [ 33 69 105]]

投稿2020/10/21 02:23

kirara0048

総合スコア1399

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

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

jeanbiego

2020/10/21 03:01

reshapeの処理は美しいですね。思いつきませんでした。 一点、下記は m = subS.shape[1] reshaped = subS.reshape(-1, m, m) こうしないと列数等分にならなくないですか。 col = subS.shape[1] row = subS.shape[0] reshaped = subS.reshape(-1, int(row/col), col)
jeanbiego

2020/10/21 03:03

あ、こっちのほうがきれいですかね。 m = subS.shape[1] reshaped = subS.reshape(m, -1, m)
kirara0048

2020/10/21 03:56

質問文にmとnが同じ数の場合の例しかないのでわかりづらいのですが、 > 列数m、行数nの行列が欲しい とあるので、オリジナルが12行3列ならば出力は4行3列になるという理解のもと、そうなるように隣り合う行を合計するコードを書きました。 つまり、一列目が[1 2 3 4 5 6 7 8 9 10 11 12]ならば「3つずつに」分割して[1+2+3 / 4+5+6 / 7+8+9 / 10+11+12]という計算をする、したがって出力配列の一列目は[6 15 24 33]となるというのが私の理解です。 jeanbiegoさんのコードだと[1 2 3 4 5 6 7 8 9 10 11 12]とある列が「3等分」されて[1 2 3 4 / 5 6 7 8 / 9 10 11 12]というふうになりますが、このあとどういう計算(足し算)を期待していますか?
jeanbiego

2020/10/21 05:00

あ、わかりました。 質問文に「行数をm等分して、新たに列数m、行数n」とありますけれど、行数をm等分してそれぞれの和をとったら、新たに出来上がるのは列数m、行数mですよね。前半と後半が噛み合ってない。 私は前半を重視して「行数をm等分して、新たに列数m、行数m」を作っていて kirara0048さんは後半を重視して「行数をn等分して、新たに列数m、行数n」を作ってますね。
kirara0048

2020/10/21 05:51

たしかにそうですね、まあ質問者さんの返事待ちということで……
sabakan4040

2020/10/21 14:37

お二方、回答とお返事ありがとうございます。 私の日本語が不適切でした、、、「等分」がよろしくなかったです。 等分という言い方を避けさせていただきます。使い方が間違っていました。 正しくは「行数をmで割る。新たに列数m、行数nを作る」です。 m*nをmで割ると→n等分 ですね。早急に修正します。 kirara0048さん、ご指摘ありがとうございます。早めに気づけて助かりました。 jeanbiegoさん、誤解を招き申し訳ありません。でも答えてくださってありがとうございます。
guest

0

pandasを使った別解

Python

1import pandas as pd 2import numpy as np 3 4subS = np.array([[4.0566930769471305, 3.7447996916033945], 5 [4.993066255471194, 5.408924102596176], 6 [9.46561717954331, 8.737865947074592], 7 [7.489599383206791, 8.113386153894263]]) 8df = pd.DataFrame(subS) 9 10m = df.shape[1] 11sums = np.array([df.loc[i:i + m - 1, :].sum().to_numpy() for i in range(0, df.shape[0], m)]) 12 13print(sums)

result

1[[ 9.04975933 9.15372379] 2 [16.95521656 16.8512521 ]]

投稿2020/10/19 23:17

Daregada

総合スコア11990

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

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

sabakan4040

2020/10/19 23:23

回答ありがとうございます。 sumsの部分がすごい上級者感がします。パッと見て今の自分は理解できないので、1つ1つ分解して勉強します。非常に参考になります。 丁寧なご回答、ありがとうございます。
Daregada

2020/10/20 01:15

実際、これがいきなり書けるわけではなくて、データフレームに読み込んだ内容を表示し、shapeの値を表示し、それをlocでスライス指定に使った結果を表示し……と少しずつ組み合わせて作っていきます。
guest

0

ベストアンサー

原型がだいぶ損なわれてしまいましたが…
下記でいかがですか。

python3

1import numpy as np 2 3subS = np.array([[4.0566930769471305, 3.7447996916033945], 4 [4.993066255471194, 5.408924102596176], 5 [9.46561717954331, 8.737865947074592], 6 [7.489599383206791, 8.113386153894263]]) 7col = subS.shape[1] 8row = subS.shape[0] 9 10subS_splits = np.split(subS,col,axis=0) 11print(subS_splits) 12#[array([[4.05669308, 3.74479969], 13# [4.99306626, 5.4089241 ]]), 14# array([[9.46561718, 8.73786595], 15# [7.48959938, 8.11338615]])] 16 17subS_sums = np.array([np.sum(subS_splits[i], axis=0) for i in range(int(row/col))]) 18print(subS_sums) 19#[[ 9.04975933 9.15372379] 20# [16.95521656 16.8512521 ]]

投稿2020/10/19 22:39

jeanbiego

総合スコア3966

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

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

sabakan4040

2020/10/19 23:01

的確な回答、ありがとうございます。 for文って、文章の頭じゃなくても使えるんですね。この形は使ったことなかったです。コードも読みやすいです。ありがとうございます。 この形のfor分についても勉強してみます。
jeanbiego

2020/10/19 23:05

この形のfor文は、「内包表記」と呼ばれています。 https://note.nkmk.me/python-list-comprehension/ リストを作りたいときとかに、最初に空のリストを用意してfor文で1個ずつappendしてとかが一行で済みます。(多少、読みづらくなりますけど)
sabakan4040

2020/10/19 23:15

1行で済むのが魅力ですね。 ちょっと違和感が残りますけど、個人的にはスッキリしてて好きです。 リンクまで送っていただいてありがとうございます。 最初の時に続いて、また助けられました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問