以前、NumPyの記事でも紹介したユニバーサル関数(ufunc)は、pandasオブジェクトにも適用することもできる。

pandasオブジェクトにufuncを適用する

ufuncは配列の各要素にメソッドを適用することのできる関数であった。

復習も兼ねて簡単な例を見てみよう。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(3, 5), columns=list('abcde'))
#           a         b         c         d         e
# 0 -0.125719  1.049569 -0.161646 -0.104864 -1.177280
# 1  0.833952  2.061937  0.918614  1.445572 -0.277370
# 2 -0.791397 -1.115831 -2.159116 -1.248302 -0.553075

df.abs() # 絶対値を取得するabs関数
#           a         b         c         d         e
# 0  0.125719  1.049569  0.161646  0.104864  1.177280
# 1  0.833952  2.061937  0.918614  1.445572  0.277370
# 2  0.791397  1.115831  2.159116  1.248302  0.553075

データフレームに対し、ufuncのabs関数を適用した例だ。
データフレームの各要素に関数が適用されていることが分かる。

列または行に対して関数を適用する

1次元配列にのみ適用することのできる関数を、データフレームの列や行に適用する場合、applyメソッドを使うと良い。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(3, 5), columns=list('abcde'))

f = lambda x: x.max() - x.min()

df.apply(f)
# a    1.243462
# b    0.947623
# c    3.625063
# d    1.388880
# e    1.715745
# dtype: float64

この例では、一次元配列を引数にとる無名関数fを、applyメソッドをとおしてデータフレームの各列に適用している。
各列の最大値と最小値の差を配列として得ることができる。

また、applyメソッドの引数axisに軸を指定すると、指定した軸に応じて関数を適用させることができる。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(3, 5), columns=list('abcde'))

f = lambda x: x.max() - x.min()

df.apply(f, axis=1)
# 0    1.462984
# 1    2.891210
# 2    2.264100
# dtype: float64

axisに1を指定すると、各行に対して関数が適用される。

applyメソッドの応用

applyメソッドに渡す関数は、必ずしもスカラー値を返す必要はなく、下記の例のようにシリーズを返す関数であっても良い。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(3, 5), columns=list('abcde'))
#           a         b         c         d         e
# 0  0.133877 -0.622101  0.736368  0.224072 -0.183736
# 1  0.068433  1.441126 -0.917174  0.033197 -0.403307
# 2 -1.122784  0.649132  0.668024  0.914219  1.134725

def f(x):
    return pd.Series([x.max(), x.min()], index=['max', 'min'])

df.apply(f)
#             a         b         c         d         e
# max  0.133877  1.441126  0.736368  0.914219  1.134725
# min -1.122784 -0.622101 -0.917174  0.033197 -0.403307

pandasオブジェクトのソート機能

pandasオブジェクトをソートする場合はsort_indexメソッドを使う。
このメソッドは、元のオブジェクトを上書きせず、新しいオブジェクトを結果として返す。

import pandas as pd
import numpy as np

df = pd.DataFrame(np.arange(15).reshape(3, 5)
                 , index=[1, 0, 2]
                 , columns=list('cbead'))
#     c   b   e   a   d
# 1   0   1   2   3   4
# 0   5   6   7   8   9
# 2  10  11  12  13  14

df.sort_index()
#     c   b   e   a   d
# 0   5   6   7   8   9
# 1   0   1   2   3   4
# 2  10  11  12  13  14

df.sort_index(axis=1)
#     a   b   c   d   e
# 1   3   1   0   4   2
# 0   8   6   5   9   7
# 2  13  11  10  14  12

引数axisに軸を指定することもでき、軸に1を指定した場合は列ラベルによるソートがおこなわれる。

降順ソート

sort_indexはデフォルトで昇順によるソートがおこなわれるが、降順によるソートをおこなうこともできる。

df.sort_index(axis=1, ascending=False)
#     e   d   c   b   a
# 1   2   4   0   1   3
# 0   7   9   5   6   8
# 2  12  14  10  11  13

値によるソート

値によるソートをおこなう場合、sort_valuesメソッドを使用する。

import pandas as pd
import numpy as np

series = pd.Series([-5, 8, 3, 1])

series.sort_values()
# 0   -5
# 3    1
# 2    3
# 1    8

series.sort_values(ascending=False)
# 1    8
# 2    3
# 3    1
# 0   -5

データフレームに対し、値によるソートを適用する場合は、オプションとして列(キー)を渡す必要がある。

import pandas as pd
import numpy as np

df = pd.DataFrame({'a': [-5, 8, 1, 2], 'b': [3, 9, -8, -1]})
#    a  b
# 0 -5  3
# 1  8  9
# 2  1 -8
# 3  2 -1

df2 = df.sort_values(by='b')
print(df2)
#    a  b
# 2  1 -8
# 3  2 -1
# 0 -5  3
# 1  8  9

df3 = df.sort_values(by='a', ascending=False)
print(df3)
#    a  b
# 1  8  9
# 3  2 -1
# 2  1 -8
# 0 -5  3

複数の列(キー)によるソートをおこないたい場合、以下のようにbyオプションに配列形式で値を渡す。

import pandas as pd
import numpy as np

df = pd.DataFrame({'a': [0, 0, 1, 1], 'b': [3, 9, -8, -1]})
#    a  b
# 0 -5  3
# 1  8  9
# 2  1 -8
# 3  2 -1

df2 = df.sort_values(by=['a', 'b'], ascending=[True, False])
print(df2)
#    a  b
# 1  0  9
# 0  0  3
# 3  1 -1
# 2  1 -8

ascendingオプションにも配列を渡すことが可能で、上記の例では第一キーは昇順、第二キーは降順によるソートをおこなっている。