目次
- 目次
- はじめに
- DataFrameのメモリサイズや、各列の型などを確認する。
- DataFrameの一部をカテゴリデータに変換する
- 複数の条件式を使って、DataFrameの一部を抽出する
- MultiIndexで特定のレベルのindexを取得する
- Pandasのapplyを高速化する
- applyにプログレスバーをつけたい。
- 参考資料
- MyEnigma Supporters
はじめに
大量のデータを処理する時にPythonのPandasは
非常に便利なライブラリですが、
久しぶりにPandasを使うと、
このようなことをしたい時にどうすればいいんだっけと
毎回調べることになるので、自分がよく調べ直す事柄をメモしておきます。
DataFrameのメモリサイズや、各列の型などを確認する。
df.info()関数を使うと、簡単に確認できます。
In [30]: df = pd.DataFrame( ...: index = ["Alice", "Bob", "Charlie", "Dave", "Ellen", "Frank"], ...: data={'age': [24, 42, 18, 68, 24, 30], ...: 'state': ["NY", "CA", "CA", "TX", "CA", "NY"], ...: 'point': [64, 92, 70, 70, 88, 57] ...: } ...: ) In [31]: df.info() <class 'pandas.core.frame.DataFrame'> Index: 6 entries, Alice to Frank Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 age 6 non-null int64 1 state 6 non-null object 2 point 6 non-null int64 dtypes: int64(2), object(1) memory usage: 192.0+ bytes
DataFrameの一部をカテゴリデータに変換する
as.type("category")でカテゴリデータに変換できます。
In [30]: df = pd.DataFrame( ...: index = ["Alice", "Bob", "Charlie", "Dave", "Ellen", "Frank"], ...: data={'age': [24, 42, 18, 68, 24, 30], ...: 'state': ["NY", "CA", "CA", "TX", "CA", "NY"], ...: 'point': [64, 92, 70, 70, 88, 57] ...: } ...: ) In [31]: df.info() <class 'pandas.core.frame.DataFrame'> Index: 6 entries, Alice to Frank Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 age 6 non-null int64 1 state 6 non-null object 2 point 6 non-null int64 dtypes: int64(2), object(1) memory usage: 192.0+ bytes In [32]: df["state"]=df["state"].astype("category") In [33]: df.info() <class 'pandas.core.frame.DataFrame'> Index: 6 entries, Alice to Frank Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 age 6 non-null int64 1 state 6 non-null category 2 point 6 non-null int64 dtypes: category(1), int64(2) memory usage: 282.0+ bytes
今回の例の場合は、データ数が小さいため、
全体のメモリ消費量が減っていませんが、
データが大きい時には、
メモリの消費量や検索スピードが高速化します。
また、read_csvで読み込んだデータをカテゴリデータ化するよりも、
read_csv関数のdtype引数でカテゴリデータ指定したほうがメモリ消費量が少なくすみます。
df = pd.read_csv("data.csv", dtype={"state":"category"})
複数の条件式を使って、DataFrameの一部を抽出する
複数の条件を使って、DataFrameの一部を抽出したいときは、
下記のように、それぞれの条件のboolean seriesを作って、
それぞれを&, |で条件をつなげると複数条件の検索結果を抽出できます。
各条件をちゃんと()つけなかったり、and, orではエラーが出ることに注意が必要です。
In [6]: import pandas as pd In [7]: df = pd.DataFrame( ...: index = ["Alice", "Bob", "Charlie", "Dave", "Ellen", "Frank"], ...: data={'age': [24, 42, 18, 68, 24, 30], ...: 'state': ["NY", "CA", "CA", "TX", "CA", "NY"], ...: 'point': [64, 92, 70, 70, 88, 57]} ...: ) In [8]: df[(df["age"]>=20) & (df["state"]=="CA")] Out[8]: age state point Bob 42 CA 92 Ellen 24 CA 88
MultiIndexで特定のレベルのindexを取得する
get_level_values()関数を使うと特定のレベルの値を取得できます。
Pandasのapplyを高速化する
DataFrameの複数の列のデータから、新しい列を計算したい場合は、
applyを使うのが普通ですが、下記のツイートのようにnp.vectorizeを使うほうが、
高速で、読みやすいコードになると思います。
In [23]: import pandas as pd In [24]: import numpy as np In [25]: df = pd.DataFrame( ...: index = ["Alice", "Bob", "Charlie", "Dave", "Ellen", "Frank"], ...: data={'age': [24, 42, 18, 68, 24, 30], ...: 'state': ["NY", "CA", "CA", "TX", "CA", "NY"], ...: 'point': [64, 92, 70, 70, 88, 57] ...: } ...: ) In [26]: df["ageXpoint"] = np.vectorize(lambda age, point: age*point)( ...: df["age"], df["point"]) In [27]: df Out[27]: age state point ageXpoint Alice 24 NY 64 1536 Bob 42 CA 92 3864 Charlie 18 CA 70 1260 Dave 68 TX 70 4760 Ellen 24 CA 88 2112 Frank 30 NY 57 1710
初めの図のようなfuncの処理を行いたい時、df.applyするよりvectorization(?)処理にすると100倍速いよと書いてる記事があって参考になった😇
— ML_Bear (@MLBear2) 2021年11月2日
別記事曰くnp.vectorizeでも同じことができるらしい。こっちは変換時間(?)分不利だけど脳死で書けるので楽https://t.co/c80tYsUJwAhttps://t.co/q4hFRC7ezq pic.twitter.com/kC0r7hILiO
applyにプログレスバーをつけたい。
df.applyをdf.progress_applyに変えるとプログレスバーが表示されるやつ義務教育で教えるべき。
— fkubota🦉 (@fkubota_) 2021年11月2日
ちゃんと書くとこうやで
— fkubota🦉 (@fkubota_) 2021年11月2日
from tqdm import tqdm
tqdm.pandas()
result = df.progress_apply(hoge)
参考資料
MyEnigma Supporters
もしこの記事が参考になり、
ブログをサポートしたいと思われた方は、
こちらからよろしくお願いします。