Numpy
其實是最早的處理數據的Python
庫,它的核心ndarray
對象,是一個高效的n維數組結構。
通過這個庫,可以高效的完成向量和矩陣運算,由於其出色的性能,很多其他的數據分析,科學計算或者機器學習相關的Python
庫都或多或少的依賴於它。
Pandas
就是其中之一,Pandas
充分利用了NumPy
的數組運算功能,使得數據處理和分析更加高效。
比如,Pandas
中最重要的兩個數據結構Series
和DataFrame
在內部就使用了NumPy
的ndarray
來存儲數據。
在使用Pandas
進行數據分析的過程中,按條件檢索和過濾數據是最頻繁的操作。
本文介紹兩種通過結合Numpy
,一方面讓Pandas的檢索過濾代碼更加簡潔易懂,另一方面還能保障檢索過濾的高性能。
1. 準備數據
第一步,先準備數據,這次使用二手房交易數據,可從 https://databook.top/lianjia/nj 下載。
import pandas as pd
import numpy as np
# 這個路徑替換成自己的路徑
fp = r'D:\data\南京二手房交易\南京江寧區.csv'
df = pd.read_csv(fp)
df.head()
2. 一般條件判斷(np.where)
比如,買房前我們想先分析下已有的成交信息,對於房價能有個大致的印象。
下面,按照總價和單價,先挑選總價200~300萬之間,或者單價1萬以下的成交信息。
符合條件返回“OK”,否則返回“NG”。
def filter_data(row):
if row["totalPrice"] > 200 and row["totalPrice"] < 300:
return "OK"
if row["unitPrice"] < 10000:
return "OK"
return "NG"
df["評估"] = df.apply(filter_data, axis=1)
df[df["評估"] == "OK"].head()
上面的過濾數據寫法是使用Pandas
時用的比較多的方式,也就是將過濾條件封裝到一個自定義函數(filter_data
)中,然後通過 apply
函數來完成數據過濾。
下面我們用Numpy
的 np.where
接口來改造上面的代碼。np.where
類似Python
編程語言中的if-else
判斷,基本語法:
import numpy as np
np.where(condition[, x, y])
其中:
- condition:條件表達式,返回布爾數組。
- x 和 y:可選參數,
condition
爲True
,返回x
,反之,返回y
。
如果未提供x
和 y
,則函數僅返回滿足條件的元素的索引。
改造後的代碼如下:
# 根據單價過濾
cond_unit_price = np.where(
df["unitPrice"] < 10000,
"OK",
"NG",
)
# 先根據總價過濾,不滿足條件再用單價過濾
cond_total_price = np.where(
(df["totalPrice"] > 200) & (df["totalPrice"] < 300),
"OK",
cond_unit_price,
)
df["評估"] = cond_total_price
df[df["評估"] == "OK"].head()
運行之後返回的結果是一樣的,但是性能提升很多。
如果數據量是幾十萬量級的話,你會發現改造之後的代碼運行效率提高了幾百倍。
3. 複雜多條件判斷(np.select)
上面的示例中,判斷還比較簡單,屬於if-else
,也就是是與否的判斷。
下面設計一種更復雜的判斷,將成交信息評估爲“優良中差”4個等級,而不僅僅是“OK”和“NG”。
我們假設:
- 優:房屋精裝,且位於中樓層,且近地鐵
- 良:總價<300,且近地鐵
- 中:總價<400
- 差:其他情況
用傳統的方式,同樣是封裝一個類似filter_data
的函數來判斷“優良中差”4個等級,然後用 apply
函數來完成數據過濾。
這裏就不演示了,直接看結合Numpy
的np.select
接口,高效的完成“優良中差”4個等級的過濾。
np.select
類似Python
編程語言中的match
匹配,基本語法:
numpy.select(condlist, choicelist, default=0)
其中:
- condlist:條件列表,每個條件都是一個布爾數組。
- choicelist:與 condlist 對應的數組列表,當某個條件爲真時,返回該位置對應的數組中的元素。
- default:可選參數,當沒有條件爲真時返回的默認值。
# 設置 “優,良,中” 的判斷條件
conditions = [
df["houseInfo"].str.contains("精裝")
& df["positionInfo"].str.contains("中樓層")
& df["advantage"].str.contains("近地鐵"),
(df["totalPrice"] < 300) & df["advantage"].str.contains("近地鐵"),
df["totalPrice"] < 400,
]
choices = ["優", "良", "中"]
# 默認爲 “差”
df["評估"] = np.select(conditions, choices, default="差")
df.head()
這樣,就實現了一個對成交信息的分類。
4. 總結
np.where
和 np.select
的底層都是向量化的方式來操作數據,執行效率非常高。
所以,我們在使用Pandas分析數據時,應儘量使用np.where
和 np.select
來幫助我們過濾數據,這樣不僅能夠讓代碼更加簡潔專業,而且能夠極大的提高分析性能。