NumPyとPandasの意外と知らない10の関数 【コードあり】

NumPyとPandasはデータサイエンスを行う上で重要な役割を果たしています。これらがなければ今日のデータ分析は非常に困難になるといっても過言ではありません。この記事では、そんなNumPyとPandasをより便利に使うための機能を紹介します。

NumPy

まずはNumPyから紹介します。ご存知の通り、NumPyは、Pythonによる科学計算のための基本パッケージの1つです。パソコンにインストールすることもできますし、クラウドで使えるGoogle Colaboratoryにも最初からNumPyが用意されていることはGoogle Colaboratoryでデータサイエンスを始めよう【使い方入門】でまとめた通りです。

このNumPyを自在に使うことが、データサイエンスに入門するための必須素養の1つです。

argpartition()

NumPyにあるargmaxだと最大値のインデックスしか取れません。上位k件のインデックスが欲しい場合には、argpartitionが便利です。

import numpy as np
# まずは適当なアレイを用意
x = np.array([12, 10, 12, 0, 6, 8, 9, 1, 16, 4, 6, 0])
# ソートはされていない上位4件のインデックスを取得してみる
index_val = np.argpartition(x, -4)[-4:]
index_val # 結果はarray([1, 8, 2, 0], dtype=int64)
# ソートし値を出力する
np.sort(x[index_val]) #結果はarray([10, 12, 12, 16])

allclose()

2つのアレイが近い値かどうかを比べるには、allcloseが便利です。どれくらい近いかは第3引数で指定できます。

import numpy as np
array1 = np.array([0.12,0.17,0.24,0.29])
array2 = np.array([0.13,0.19,0.26,0.31])
# 違いが0.1までであればTrueを返す
np.allclose(array1,array2,0.1) #結果はFalse
# 違いが0.2までであればTrueを返す
np.allclose(array1,array2,0.2) #結果はTrue

clip()

clip()は、アレイの値を一定の範囲に収めるために使われます。 (アレイ, 下限, 上限) の順番です。

import numpy as np
x = np.array([3, 17, 14, 23, 2, 2, 6, 8, 1, 2, 16, 0])
# アレイxを下限2, 上限5にする
np.clip(x,2,5) # 結果はarray([3, 5, 5, 5, 2, 2, 5, 5, 2, 2, 5, 2])

extract()

Extractは抽出するという意味ですが、extract関数はその名の通り条件を満たすものを抽出関数です。 (条件, 配列) という形で記載します。

import numpy as np
# 0から19までの整数を適当に12個取り出して配列を作ります
array = np.random.randint(20, size=12)
array # 乱数によって変わりますが、例えばarray([ 0,  1,  8, 19, 16, 18, 10, 11,  2, 13, 14,  3]) となります
#  2で割って1あまる (つまり奇数) かどうかをチェックします
cond = np.mod(array, 2)==1
cond # 結果はarray([False,  True, False,  True, False, False, False,  True, False, True, False,  True])
# この条件を満たすもの (つまり奇数) だけを抽出します
np.extract(cond, array) # 結果はarray([ 1, 19, 11, 13,  3])
# 条件は直接記述することもできます。たとえば3未満または15より大きいものを抽出してみます
np.extract(((array < 3) | (array > 15)), array) # 結果はarray([ 0,  1, 19, 16, 18,  2])

where()

whereもある条件を満たす要素のインデックスを取得できます。また、条件を満たす場合と満たさない場合で違う処理を行うことも可能です。

import numpy as np
y = np.array([1,5,6,8,1,7,3,6,9])
# 5よりも大きい要素のインデックスを返します
np.where(y>5) # 結果はarray([2, 3, 5, 7, 8], dtype=int64),)

# 5よりも大きいものはHit, そうでないものはMissと置き換えます
np.where(y>5, "Hit", "Miss")
# 結果はarray(['Miss', 'Miss', 'Hit', 'Hit', 'Miss', 'Hit', 'Miss', 'Hit', 'Hit'])

Pandas

pandasは、特に表形式のデータを簡単に直感的に操作できるように設計されたPythonパッケージです。

read_csv(nrows=n)

read_csv関数は知っている方も少なくないと思いますが、csvの一部だけを読むことができるのは知らない方もいます。しばしばデータが巨大になるので、nrows引数で読み込む行数を指定した方がスマートです。

import pandas as pd
import io
import requests
#  ファイルをwebからダウンロードする (手持ちのcsvファイルでもOKです)
url = "https://raw.github.com/vincentarelbundock/Rdatasets/master/csv/datasets/AirPassengers.csv"
s = requests.get(url).content
# 最初の10行だけ読み込む
df = pd.read_csv(io.StringIO(s.decode('utf-8')),nrows=10 , index_col=0)

map()

map()関数は、シリーズデータに関数をまとめて適用させるために使われています。

import pandas as pd
#  乱数からなるデータフレーム を作成する
dframe = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'), index=['India', 'USA', 'China', 'Russia'])
# 小数点2桁に丸める無名関数を作成
changefn = lambda x: '%.2f' % x
# データフレームのd列に関数を適用
dframe['d'].map(changefn)

apply()

apply()を使用すると、ユーザーは関数を渡して、Pandasシリーズのすべての値に適用できます。

import pandas as pd
# 最大と最小値の差を計算する無名関数
fn = lambda x: x.max() - x.min()
# 全ての列に無名関数を適用する
dframe.apply(fn)

isin()

isin()は、データフレームのフィルターを行う関数で、特に複数のフィルターを設定したい時に役立ちます。

import pandas as pd
# read_csv関数の例で読み込んだデータセットに2つのフィルターを適用してみる
filter1 = df["value"].isin([112]) 
filter2 = df["time"].isin([1949.000000])
df [filter1 & filter2]

copy()

copy()は、Pandasオブジェクトのコピーを作成するために使用されます。データフレームを別のデータフレームに割り当てると、別のデータ・フレームで変更を行ったときに値が変更されます。copy()を使うとこの問題を防ぐことができます。

import pandas as pd
# 例えば適当なシリーズを作成してみます
data = pd.Series(['India', 'Pakistan', 'China', 'Mongolia'])
# data1に = で代入します
data1= data
# 新しいdata1の最初の要素を書き換えると
data1[0]='USA'
# もともとのdataも書き換わってしまっています
data
# これを防ぐには、copy関数を使えばOKです
new = data.copy()
# 新しいnewを書き換えても
new[1]='Changed value'
# 古いdataは置き換わっていません
print(new) 
print(data)

関連サイト・図書

この記事に関連した内容を紹介しているサイトや本はこちらです。

Google Colaboratoryでデータサイエンスを始めよう【使い方入門】

まとめ

最後に今回の内容をまとめます。

  • NumPyのextractで要素を簡単に抽出できる
  • Pandasオブジェクトのmapとapplyで自作関数を適用できる
  • Pandasオブジェクトをコピーする時には注意

今日も【生命医学をハックする】 (@biomedicalhacks) をお読みいただきありがとうございました。