條件過濾是我們在處理資料最常遇到的需求~
先準備一下今天要用到的data。
做一個很常見的成績表。
df = pd.DataFrame({"name":pd.Series(["Mary", "John", "Cindy", "Bojack", "Zoy", "Taylor", "Denny", "Mike", "Bob", "Peter"]),
"grade":pd.Series(["6", "7", "8", "6", "7", "8", "6", "7", "8", "6"])})
df[["art","math","physics","history","english","sport"]] = np.random.randint(50, 100, size=(len(df), 6))
bool篩選是利用我們提供條件讓程式判斷回傳true/false。
df["grade"] > 7
這時pandas會回傳一個series,跟grade欄位長度一致的series,告訴我們grade中的每一列是否符合大於7(>7)的條件,依照我們的data會回傳如下的陣列。
false
false
true
false
false
true
false
false
true
false
除了用python的算符外,我們也可以使用series方法,以下兩行是一樣的效果
df["grade"] > 7
df["grade"].gt(7)
其他的比較運算符號
小於 | 大於 | 小於等於 | 大於等於 | 等於 | 不等於 |
---|---|---|---|---|---|
< | > | <= | >= | == | != |
lt | gt | le | ge | eq | ne |
把運算式放到df裡,pandas會回傳符合這個條件的所有欄位df[df["grade"] > 7]
用位元算符相符,並且每個條件用()括號包起來:
#篩選名為Bojack的學生
df[df["name"] == "Bojack"]
#篩選大於7年級 "並且" 歷史大於等於80分的學生
df[(df["grade"] > 7) & (df["history"] >= 80)]
#篩選物理大於85 "或者" 歷史大於等於80分的學生
df[(df["physics"] > 85) | (df["history"] >= 80)]
#篩選除了Taylor外,art大於等於80分的學生
df[~(df["name"] == "Taylor") & (df["art"] >= 80)]
df[df["name"].str.contains("M")] #名字裡面有M的學生
df[df["name"].str.startswith("M")] #名字以M開頭的學生
df[df["name"].str.endswith("y")] #名字以y結尾的學生
如果有比對值不只一個,很多個or組起來不只打字很累還看得很亂,這就是in出現的好時機了
需求:篩選出名字為["Bojack", "Zoy"]的學生df[df["name"].isin(["Bojack", "Zoy"])]
#篩選英文分數介於60-90間的學生
df[df["english"].between(60, 90)]
熟悉sql的朋友有福了,用query簡直小魚游回太平洋那麼悠游自在。
df.query("english > 60 and english < 80")
df.query("grade in [6, 7]")
df.query("grade not in [6, 7]")
df.query("not name == 'Bojack'")
#條件裡的grade要是很多個的話,可以先寫成陣列,再用@去接變數
inGrade = [6, 7]
df.query("grade not in @inGrade")
雖然day2有簡單帶過,但它實在強大到可以再仔細講講
df.loc[指定列, 指定欄]
指定列/欄可用於index label,list、切片、bool篩選
要用指定列,就必須先set index,選擇器才能用index label去找data
#先把index設為name,之後就可以用name來操作
df = df.set_index("name")
#回傳單一值:Mary這列的物理成績
df.loc["Mary", "physics"]
#回傳Series: 把Mary這列的所有值回傳series,並把欄名做為label
df.loc["Mary"] # 單一值
#回傳DataFrame: Mary/Taylor的完整列
df.loc[["Mary", "Taylor"]]
#回傳DataFrame: 列Cindy~Taylor的欄位art~physic
df.loc['Cindy':'Taylor', "art":"physics"]
#回傳DataFrame: 所有列的欄位art~physic
df.loc[:, "art":"physics"]
有幾個地方要注意一下
df.loc["Mary"]
df.loc[["Mary"]]
df.loc["Mary"]
等同於 df.loc["Mary", :]
前面說過篩選了,這邊就不多做介紹
#篩選出grade為7年級,僅列出欄位physics和math
df.loc[df["grade"] == 7, ["physics","math"]]
#把mary的數學成績改為100
df.loc["Mary", "math"] = 100
#把Bojack, Taylor的art成績改為93
df.loc[["Bojack", "Taylor"], "art"] = 93
#美術老師佛心大開,把不及格的都改成及格
df.loc[df["art"] < 60, "art"] = 60
# 新增一列
df.loc["Ivy"] = np.random.randint(50, 100, 8)
# 新增一欄
df.loc[:, "passed"] = df["math"] >= 60
明天來講講讀寫資料。