スタートページ> JavaScript> 他言語> Python 目次> ←配列の部分指定と行・列の追加 →DataFrame のSQLライクな操作
Python での計算は、あくまでもスカラー間の計算です。 list配列全体に同じ演算をするには forループ などを用いることになります。 配列を対象にした場合、mlist[1][2] はスカラーなので、mlist[1][2] = 100 はできます。 しかし、mlist = 100 のように配列要素全体を対象にする式はエラーになります。 このときは for ループを用いたプログラムを作成する必要があります。 それに対して、NumPy で marray = np.array([…],[…],…]) のように定義した ndarray配列では、 marray = 100 の1行で全要素を100にするような命令ができます。 Python では基本的にスカラー間の演算ですので、 ここでは主に、ndarray と DataFrame を対象にします。
以降、次のデータをサンプルとして用います。
import numpy as np import pandas as pd vlist = [10, 11, 12, 13] varray = np.array([10, 11, 12, 13]) mlist = [[ 0, 1, 2, 3], [10, 11, 12, 13], [20, 21, 22, 23]] marray = np.array([[ 0, 1, 2, 3], [10, 11, 12, 13], [20, 21, 22, 23]]) # c0 c1 c2 c3 df = pd.DataFrame([[ 0, 1, 2, 3], [10, 11, 12, 13], [20, 21, 22, 23]], columns = ['c0','c1','c2','c3'])
配列の全要素に加減乗除が行われます varray + 100 # 〇 array([110, 111, 112, 113]) marray * 2 # 〇 array([[ 0, 2, 4, 6], [20, 22, 24, 26], [40, 42, 44, 46]]) df + 100 # 〇 全要素が +100 されます df['c1'] + 100 # 〇 c1列の列要素が +100 されます df.loc[1] * 2 # 〇 行番号1の行要素が *20 されます 順を逆にしても、同じ結果になります。 100 - varray # 〇 array([90, 89, 88, 87])
双方のベクトルの長さが同じでなければなりません。順を逆にしても、同じ結果になります。 v = [100, 100, 100, 100] # v は ndarray でも同じです。 varray + v # 〇 array([110, 111, 112, 113]) df.loc[1] + v # 〇 行番号1の行要素が加算されます v = [100, 100, 100] df['c1'] + v # 〇 c1列の列要素が +100 されます。
双方のベクトルの長さが同じでなければなりません。 v = [1, 2, 3, 4] varray * v # 〇 array([10, 22, 36, 52]) v * varray # 〇 同上 df.loc[1] * v # 〇 v = [1, 2, 3] df['c1'] * v # 〇 1 22 63 になる # df['c1'] が縦ベクトル、v が横ベクトルなのに、各要素の乗算になる
内積には * ではなく @ を用います。
双方のベクトルの長さが同じでなければなりません。
被乗数のベクトルが横ベクトルでも縦ベクトルでも構いません。
v = [1, 0, 1, 0]
varray @ v # 〇 22 (=10*1 + 11*0 + 12*1)
df.loc[1] @ v # 〇 同上
v = [1, 0, 1]
df['c1'] @ v # 〇 22 (=1*1 + 11*0 + 12*1)
v @ df['c1'] # 〇 同上
各列に横ベクトルを加算・乗算する v = [100, 200, 300, 400] marray + v # 〇 array([[100, 201, 302, 403], # [110, 211, 312, 413], # [120, 221, 322, 423]]) marray * v # 〇 array([[ 0, 200, 600, 1200], # [1000, 2200, 3600, 5200], # [2000, 4200, 6600, 9200]]) df + v # 〇 c0 c1 c2 c3 # 0 100 201 302 403 # 1 110 211 312 413 # 2 120 221 322 423 df.add(v, axis=1) # 〇 同上 df.mul(v, axis=1) # 〇 各行に縦ベクトルを加算・乗算する v = [[100], [200], [300]] # 縦ベクトルにする必要がある marray + v # 〇 array([[100, 101, 102, 103], # [210, 211, 212, 213], # [320, 321, 322, 323]]) marray * v # 〇 array([[ 0, 100, 200, 300], # [2000, 2200, 2400, 2600], # [6000, 6300, 6600, 6900]]) df + v # × エラー v が縦ベクトル df * v # × エラー 各行に横ベクトルを加算・乗算する v = [100, 200, 300] # 横ベクトル df.add(v, axis=0) # 〇 c0 c1 c2 c3 # 0 100 101 102 103 # 1 210 211 212 213 # 2 320 321 322 323 df.mul(v, axis=0) # 〇 c0 c1 c2 c3 # 0 0 100 200 300 # 1 2000 2200 2400 2600 # 2 6000 6300 6600 6900
両方のサイズが同じでなければなりません。 m = [[1000, 1100, 1200, 1300], # m は mlist, marray どちらでも有効です。 [2000, 2100, 2200, 2300], [3000, 3100, 3200, 3300]] ndarray では「行列とベクトル」での方法と同じです。 marray + m # 〇 array([[1000, 1101, 1202, 1303], # [2010, 2111, 2212, 2313], # [3020, 3121, 3222, 3323]]) marray * m # 〇 array([[ 0, 1100, 2400, 3900], # [20000, 23100, 26400, 29900], # [60000, 65100, 70400, 75900]]) DataFrame のときは、m は転置してサイズを合わせる必要があります。 m = [[1000, 2000, 3000], [1100, 2100, 3100], [1200, 2200, 3200], [1300, 2300, 3300]] df * m # 〇 c0 c1 c2 c3 # 0 0 1100 2400 3900 # 1 20000 23100 26400 29900 # 2 60000 65100 70400 75900
内積には * ではなく @ を用います。 行列Aのサイズを (ma*na)、Bを (mb*nb) としたとき、na = mb でなければならず、 結果は ma*nb は配列になります。 m = [[0, 1], # mlist でも marray でもよい [1, 0], [0, 1], [1, 0]] marray @ m # 〇 array([[ 4(= 0*0 + 1*1 + 2*0 + 3*1), 2(= 0*1 + 1*0 + 2*1 + 3*0)], # [24(=10*0 + 11*1 + 12*0 + 13*1), 22(=10*1 + 11*0 + 12*1 + 13*0)], # [44(=20*0 + 21*1 + 22*0 + 23*1), 42(=20*1 + 21*0 + 22*1 + 23*0)]]) df @ m # 〇 0 1 列名が失われます。 # 0 4 2 # 1 24 22 # 2 44 42
転置行列とは、行・列を入れ替えた行列です。T属性を用います。 ベクトルには使えません。行列だけです。 list の行列には使えません marray = np.array([[ 0, 1, 2], [10, 11, 12]]) marray.T # array([[ 0, 10], # [ 1, 11], # [ 2, 12]]) df = pd.DataFrame([[ 0, 1, 2], [10, 11, 12]], columns = ['c0','c1','c2'], index = ['r0','r1']) df.T # r0 r1 # c0 0 10 # c1 1 11 # c2 2 12
一般形: df.xxx(変数、axis = 'columns') xxx = add(+)、sub(-)、mul(*)、div(/,//)、mod(%)、pow(**) axis = 0(横方向), 1(縦方向) 機能は二項演算子と同じで、二項演算子を用いるほうが簡便ですが、上記のように、行を対象にする場合は、これを用いるのが便利です。
NumPy では、通常のプログラム言語で提供しているものと同等な関数を提供しています。 通常は、変数がスカラーなら戻り値もスカラー、配列なら戻り値も配列になります。 元データ import numpy as np import pandas as pd s = 4 vlist = [4, 9] marray = np.array([[4, 9], [16, 25]]) df = pd.DataFrame([[4, 9], [16, 25]], columns= ['c0','c1']) 関数 np.sqrt(s) # 2.0 np.sqrt(vlist) # array([2., 3.]) np.sqrt(marray) # array([[2., 3.], [4., 5.]]) np.sqrt(df) # c0 c1 # 0 2.0 3.0 # 1 4.0 5.0 代表的な数学関数 累乗(np.power)・平方根(np.sqrt)、三角関数(np.sin, np.cos, np.tan)、指数関数(np.exp)、対数関数(np.log)、 切り捨て(np.floor)、切り上げ(np.ceil)、四捨五入(np.round)、絶対値(np.abs)、… 参照:DepAge「NumPyの数学関数・定数まとめ」
NumPy、Pandas での基本的な関数を列挙します。 sum(): 合計、mean(): 平均、min(): 最小、max(): 最大、std(): 標準偏差、var(): 分散など 一般形: A np.sum(配列, axis=0/1) list, ndarray, DataFrame 全てに使える B 配列.sum(axis=0/1) list には使えない axis 全体を対象にするときは与えない 結果はスカラー =0 行列の縦方向集計 結果はサイズ列数のベクトル 1 行列の横方向集計 結果はサイズ行数のベクトル
ここでは次のデータをサンプルとして用います。
import numpy as np import pandas as pd varray = np.array([10, 11, 12, 13]) marray = np.array([[ 0, 1, 2, 3], [10, 11, 12, 13], [20, 21, 22, 23]]) # c0 c1 c2 c3 df = pd.DataFrame([[ 0, 1, 2, 3], [10, 11, 12, 13], [20, 21, 22, 23]], columns = ['c0','c1','c2','c3'])
ベクトル 結果はスカラー vlist.sum() # エラー np.sum(vlist) # 〇 46 (= 10+11+12+13) np.sum(varray) # 〇 46 varray.sum() # 〇 46 np.sum(df['c1']) # 〇 33 (= 1+11+21) df['c1'].sum() # 〇 33 行列全体 結果はスカラー np.sum(marray) # 〇 138 marray.sum() # 〇 138 np.sum(df) # × 各列ごとの集計になる 30 33 36 39 df.sum() # × 各列ごとの集計になる 30 33 36 39 df.sum().sum() # 〇 138 行列の縦方向集計 結果はサイズ列数のベクトル np.sum(marray, axis=0) # 〇 array([30, 33, 36, 39]) marray.sum(axis=0) # 〇 np.sum(df) # 〇 np.sum(df, axis=0) # 〇 df.sum() # 〇 c0 30 # c1 33 # c2 36 # c3 39 df.sum(axis=0) # 〇 行列の横方向集計 結果はサイズ行数のベクトル np.sum(marray, axis=1) # 〇 array([ 6, 46, 86]) marray.sum(axis=1) # 〇 np.sum(df, axis=1) # 〇 df.sum(axis=1) # 〇 0 6 # 1 46 # 2 86
ここでは次のデータをサンプルとして用います。
import numpy as np import pandas as pd vlist = [300, 112, 412, 513, 214] varray = np.array([300, 112, 412, 513, 214]) marray = np.array([[ 0, 400, 2, 3, 4], [300, 100, 300, 500, 200], [600, 500, 22, 23, 24], [ 30, 200, 32, 33, 34], [ 40, 400, 42, 43, 44]]) df = pd.DataFrame([[ 0, 400, 2, 3, 4], [300, 100, 300, 500, 200], [600, 500, 22, 23, 24], [ 30, 200, 32, 33, 34], [ 40, 400, 42, 43, 44]], columns = ['c0','c1','c2','c3','c4'])
np.sort(vlist) # array([112, 214, 300, 412, 513]) list も ndarray になる np.sort(varray) # 上と同じ np.sort(varray)[::-1] # 降順 array([513, 412, 300, 214, 112]) # 元の配列は維持 array([300, 112, 412, 513, 214]) 次の記述もできます(list は使えない)。しかし元の配列は破壊されます varray.sort() # array([112, 214, 300, 412, 513]) # 元の配列は破壊 array([112, 214, 300, 412, 513])
np.argsort(vlist) # array([1, 4, 0, 2, 3]) これ以外は list は使えません np.argsort(varray) # array([1, 4, 0, 2, 3]) # varray[1] は順序1, [2]は順序4, [3]は順序0, … になる varray.argsort() # 上と同じ varray[np.argsort(varray)] # array([112, 214, 300, 412, 513]) # 上の順序に並べた varray[varray.argsort()] # 同上 varray[varray.argsort()[::-1]] # 降順 array([513, 412, 300, 214, 112]) # 元の配列は維持 array([300, 112, 412, 513, 214])
その指定した行の横ベクトル、列の縦ベクトルにargsortを適用し、それにより行列をソートします。 marray[:, marray[行番号].argsort()[::-1]] marray[marray[:,列番号].argsort(), :] marray[marray[:,列番号].argsort()[::-1], :] 指定行の横ベクトルの昇順 marray[:, marray[行番号].argsort()] marray[:, marray[1].argsort()] # array([[400, 4, 0, 2, 3], # [100, 200, 300, 300, 500], 指定行 昇順 # [500, 24, 600, 22, 23], # [200, 34, 30, 32, 33], # [400, 44, 40, 42, 43]]) 指定行の横ベクトルの降順 marray[:, marray[行番号].argsort()[::-1]] marray[:, marray[1].argsort()[::-1]] # array([[ 3, 2, 0, 4, 400], # [500, 300, 300, 200, 100], 指定行 降順 # [ 23, 22, 600, 24, 500], # [ 33, 32, 30, 34, 200], # [ 43, 42, 40, 44, 400]]) 指定列の縦ベクトルの昇順 marray[marray[:,列番号].argsort(), :] marray[marray[:,1].argsort(), :] # array([[300, 100, 300, 500, 200], # [ 30, 200, 32, 33, 34], # [ 0, 400, 2, 3, 4], # [ 40, 400, 42, 43, 44], # [600, 500, 22, 23, 24]]) # └ 指定列 昇順 指定列の縦ベクトルの降順 marray[marray[:,列番号].argsort()[::-1], :] 省略 指定行が複数の場合 順位の低い行(列)で先にソートし、次に順位の高い行(列)でソートします。 marray を維持するなら次のようにしてソート後行列を work にします。 work をすべて marray にすれば、marray はソート後の行列に置き換わります。 work = marray[:, marray[2].argsort()] work = work[:, work[1].argsort()] # ┌ ┌ 第1順位では同じ値 work # array([[400, 4, 2, 0, 3], # [100, 200, 300, 300, 500], 第1順位 # [500, 24, 22, 600, 23], 第2順位 # [200, 34, 32, 30, 33], # [400, 44, 42, 40, 43]])
実務的には、特定の列によるソートがほとんどでしょう。 元の df は保存されます。 指定列の縦ベクトルによる昇順 df.sort_values(キー列名) df.sort_values('c1') # c0 c1 c2 c3 c4 # 1 300 100 300 500 200 # 3 30 200 32 33 34 # 0 0 400 2 3 4 # 4 40 400 42 43 44 # 2 600 500 22 23 24 指定列の縦ベクトルによる昇順 df.sort_values(キー列名, ascending=False) df.sort_values('c1', ascending=False) # c0 c1 c2 c3 c4 # 2 600 500 22 23 24 # 0 0 400 2 3 4 # 4 40 400 42 43 44 # 3 30 200 32 33 34 # 1 300 100 300 500 200 複数の指定列によるソート df.sort_values([キー1, キー2], ascending=[True, False]) ソート順位 ソートキーに対応した昇順・降順 df.sort_values(['c1','c0'], ascending=[True, False]) # c0 c1 c2 c3 c4 # 1 300 100 300 500 200 # 3 30 200 32 33 34 # 4 40 400 42 43 44 c2の降順 # 0 0 400 2 3 4 同上 # 2 600 500 22 23 24