・お題:DataFrameを入手した。ここから、気になるデータを抽出したりしたい。
・PandasのDataFrameで特定のデータを抽出したりできるとうれしい。
・データセットを作成する。
import pandas as pd
import numpy as np
import random
df=pd.DataFrame({"Age":[random.randint(20, 60) for n in range(100)],
"Weight":[random.randint(45, 100) for n in range(100)],
"Income":[random.randint(200, 1000) for n in range(100)],
"Sex":[random.choice(["f","m"]) for n in range(100)],
"From":[random.choice(["Tokyo","Osaka","Yokohama","Nagoya","Kobe"]) for n in range(100)]})
・これで、以下のdfができる。
・次に、適当に欠損させる。
df2=df.copy()
mask=np.random.choice([0,1],p=[0.1,0.9],size=df2.shape[0]*df2.shape[1]).reshape(df2.shape[0],df2.shape[1]).astype(bool)
df2=df2.where(mask, np.nan)
df2.info()
で
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100 entries, 0 to 99
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Age 84 non-null float64
1 Weight 92 non-null float64
2 Income 88 non-null float64
3 Sex 95 non-null object
4 From 89 non-null object
dtypes: float64(3), object(2)
memory usage: 4.0+ KB
が返ってくる。各列10%程度欠損している。
・特定の条件に合うデータを抽出するには、queryを使う。例えば、df2から、Incomeが500以上のデータをとってくる。
df2.query("Income > 500")
ちなみに、Incomeが500~800のデータをとってくるには、query("500 < Income < 800")にすれば良い。
・Sexでfをとって来る場合、クオートに気を付ける。文字列fと一緒か否かを判別するので、==を使う。また、意味の塊ごとにクオートの数を揃える。
df2.query("Sex == 'f'")
ちなみに、df2.query('Sex == "f"')でも良い。否定は、!=にする。
・特定の列で複数の条件にあてはまるデータを取得するには、リストにすれば良い。
df2.query("From == ['Tokyo','Nagoya']")
・複数の列の条件でアンド検索することもできる。Sex == mかつWeight > 80なら以下のような感じ。
df2.query("Sex == 'm' & Weight > 80")
ちなみに、オア検索は|でいける。df2.query("Sex == 'm' | Weight > 80")
・queryを使わない方法として、True/Falseの列を作成してから、行をとって来る方法もある。
df2["Sex"]=="m"
df2[df2["Sex"]=="m"]
・これを利用して、Fromにyが含まれるデータを抽出できる。
df2[df2["From"].str.contains("y", na=False)]
str.containsはデフォルトでNaNが残ってしまうので、NaNをどう処理するか、指定しておく。
・NaNのデータを除くこともできる。
df2[df2["Age"].notna()]
ちなみに、notna()をisna()にすればNaNのものだけ釣ってくることができる。
・せっかくなので昇順に並べ替えたい。sort_valuesでいける。
df2.sort_values("Age")
ちなみに、引数ascendingにFalseを与えると、降順になる。
・いろいろ使えそう。
おわり。