高性能Pandas​:eval() 與 query() 上篇

2022-01-10 Pandas中文社區

收錄於話題 #pandas 28個

正如我們在前面的文章中已經介紹過的,Python 數據科學生態環境的強大力量是建立在 NumPy 和 Pandas 的基礎之上,並通過直觀的語法將基本操作轉換成C語言:

NumPy中,是向量化/廣播式操作

Pandas中是分組式運算

雖然這些抽象功能對於許多常見的用例來說是簡潔和高效的,但它們往往依賴於臨時中間對象的創建,這樣就會佔用大量的計算時間和內存,造成算力的不必要的浪費。

從0.13版本(2014年1月正式發布)開始,Pandas引入了一些實驗性的工具,允許用戶直接運行C語言速度的操作,而不需要費力地配置中間數組。這些就是eval() 和 query() 函數。

eval()query()它們依賴於Numexpr程序包。

(https://github.com/pydata/numexpr)。

下面我們將介紹它們的使用方法,並給出我自己做項目中的一些經驗,告訴你何時可以考慮使用它們。

query() 和 eval() 的設計動機:複合表達式

前面我們已經看到,NumPy 和 Pandas 都支持快速的向量化操作;例如,對下面兩個數組進行求和:

這樣做比普通的Python 循環或列表綜合要快很多:

但這種運算在處理複合表達式的問題時,效率會變得不那麼高效。例如,考慮以下表達式:

因為 NumPy 會對每個代數子表達式進行計算,所以大致等價於以下內容:

換句話說,每一個中間步驟都在內存中顯式分配

如果x和y數組非常大,會導致大量的內存和計算開銷。

Numexpr 程序庫提供了元素到元素的複合代數式運算,而無需分配完整的中間數組。

Numexpr 文檔中有更多的細節,但簡而言之,這個程序庫其實就是用一個 NumPy 風格的字符串代數式進行運算:

好處是,Numexpr 在計算代數式時不需要為臨時數組分配全部內存,因此可以比 NumPy 更高效,尤其是對於大型數組的處理更為適合。

我們將在下面討論 Pandas 的 eval() 和 query() 工具在概念上是相似的,並且也是基于于 Numexpr 來實現的。

# 用 pandas.eval() 實現高性能運算

Pandas中的 eval() 函數使用字符串表達式實現了 DataFrames 的高性能運算。例如以下的DataFrames:

如果要用普通的 Pandas 方法計算所有四個 DataFrames 的總和,我們可以直接寫出總和:

可以通過 pd.eval  和字符串表達式計算出同樣的結果:

這個表達式的 eval() 版本比普通方法大約快了一倍(而且使用的內存少得多),同時給出了同樣的結果:

## pd.eval() 支持的運算

從Pandas v0.16版本開始,pd.eval()支持多種操作運算。為了演示這些操作,我們將使用一個整數類型的 DataFrames:

### 算術運算符

pd.eval() 支持所有的算術運算符。例如:

### 比較運算符

pd.eval() 支持所有比較運算符,包括鏈式表達式:

### 位運算符

pd.eval() 支持 & 和 | (或)等位運算符:

此外,它還支持在布爾表達式中使用 and 和 or 等字面值:

### 對象屬性與索引

pd.eval() 支持通過 obj.attr 語法獲取對象屬性,以及通過 obj[index] 語法獲取對象索引:

### 其他運算

其他的操作,如函數調用、條件語句、循環和其他更複雜的運算。目前還不能在 pd.eval() 中實現。

如果你想執行這些更複雜的表達式類型,你可以使用Numexpr 庫來實現。

# 用 DataFrame.eval() 實現列間運算

就像 Pandas 有一個頂層的 pd.eval() 函數一樣,DataFrames 也有一個 eval() 方法可以做類似的運算。

使用 eval() 方法的好處是可以藉助列名稱來進行運算。我們以這個標籤數組為例:

如果使用前面介紹的 pd.eval(),我們可以通過下面的代數式計算出這三列:

DataFrame.eval() 方法可以通過列名稱實現更簡潔的表達式:

請注意,這裡我們將列名稱作為變量來計算表達式,結果也是正確的。

## 用DataFrame.eval() 新增列

除了剛才討論的運算功能外,DataFrame.eval() 還允許創建新的列。

讓我們使用之前的 DataFrame 來演示,它有 'A'、'B' 和 'C' 列:

我們可以使用 df.eval() 來創建一個新的列'D',並給它分配一個從其他列計算出來的值:

還可以修改已有的列:

## DataFrame.eval() 使用局部變量

DataFrame.eval() 方法支持一種額外的語法,它允許它與本地 Python 變量一起工作。如下所示:

這裡的 @ 字符表示這是一個變量名,而不是一個列名,它讓你有效地評估兩個 "命名空間 "的表達式:列的命名空間和 Python 對象的命名空間。

注意這個 @ 字符只能在 DataFrame.eval() 方法中使用,而不能在 pandas.eval() 函數中使用,因為 pandas.eval()函數只能獲取一個 (Python) 命名空間的內容。

# DataFrame.query() 方法

DataFrame有另一個基於已評估字符串的方法,稱為query()方法。考慮以下內容:

就像在我們討論中使用的例子一樣DataFrame.eval(),這是一個涉及列的表達式DataFrame。

但是,不能使用DataFrame.eval()語法來表達它!

相反,對於這種類型的過濾操作,可以使用以下query()方法:

與掩蔽表達式相比,除了計算效率更高之外,它更易於閱讀和理解。請注意,該query()方法還接受@標記以標記局部變量:

# 何時使用eval()和query()

性能決定使用時機。

在考慮是否使用這些功能時,有兩個注意事項:計算時間內存使用量

內存使用是最可預測的方面。如前所述,每個涉及NumPy數組或PandasDataFrame的複合表達式都將導致隱式創建臨時數組。例如:

大致相當於:

如果DataFrame臨時佔用內存比我們電腦可用系統內存要大,(通常為數GB),則最好使用eval()  orquery()表達式。

我們可以使用以下方法檢查數組的近似大小(以字節為單位):

在性能方面,eval()即使您沒有最大限度地利用系統內存,也可以更快。

本文介紹了eval()query()的使用方法。主要是讓計算機的效率達到最高,是Pandas高級用法之一。

關注🐼君,持續學習精進。

相關焦點

  • 高性能 Pandas 方法:query 和 eval
    pip install seabornimport pandas as pdimport seaborn as sns# Load iris datasetiris = sns.load_dataset('iris')# 等價於 iris[(iris.sepal_length > 5) & (iris.petal_length &
  • 五花八門的 Pandas 篩選數據
    import pandas as pdimport numpy as npdf = pd.DataFrame({    "name":['小明','小王','張菲','關宇','孫小小','王建國','劉蓓'],    "sex":['男','女','女','男','女','男','女'],
  • 數據科學 | 從 Pandas 小白到 Pandas 能手
    在本文中,作者從 Pandas 的簡介開始,一步一步講解了 Pandas 的發展現狀、內存優化等問題。這是一篇最佳實踐教程,既適合用過 Pandas 的讀者,也適合沒用過但想要上手的小白。通過本文,你將有望發現一到多種用 pandas 編碼的新方法。Pandas 發展現狀;內存優化;索引;方法鏈;隨機提示。
  • 通過 SQL 查詢學習 Pandas 數據處理
    ://shzhangji.com/cnblogs/2017/07/23/learn-pandas-from-a-sql-perspective/Pandas 是一款廣泛使用的數據處理工具。結合 NumPy 和 Matplotlib 類庫,我們可以在內存中進行高性能的數據清洗、轉換、分析及可視化工作。雖然 Python 本身是一門非常容易學習的語言,但要熟練掌握 Pandas 豐富的 API 接口及正確的使用方式,還是需要投入一定時間的。對於數據開發工程師或分析師而言,SQL 語言是標準的數據查詢工具。
  • Python 數據分析:Pandas 進階
    import numpy as npfrom pandas import Series, DataFrames = Series(['1', '2', np.nan, '3'])df = DataFrame([['1', '2'], ['3', np.nan], [np.nan, 4]])print(s)print(df)# 清除缺失項
  • Pandas實用技能,數據篩選query函數詳細介紹
    在數據處理過程中,咱們經常會用到數據篩選,Pandas 中提供了數據篩選的多種方法,這裡,陽哥來給大家分享下 在Pandas中應用 query 函數來進行數據篩選。query 函數的一般用法如下:df.query('expression')文中的代碼是在 Jupyter Notebook 中運行的(也可以是其他IDE),本次使用的 Pandas 版本是 1.3.0 版,如下
  • Pandas | 合併數據集
    合併數據集:Concat 與 Append 操作首先導入 Pandas 和 NumPy:import pandas as pd
  • 當pandas撞上了sql,於是一個強大的pandasql庫產生了!
    2. pandasql的使用1)簡介pandas中的DataFrame是一個二維表格,資料庫中的表也是一個二維表格,因此在pandas中使用sql語句就顯得水到渠成,pandasql使用SQLite作為其操作資料庫,同時Python自帶SQLite模塊,不需要安裝,便可直接使用。
  • Expo pandas arrive in Shanghai
    Ten giant pandas selected for the world expo by the Chinese giant panda protection and research center were flown to Shanghai on Jan. 5 from the center's Bifengxia base in Ya'an City, southwest China's
  • pandas 篩選數據的 8 個騷操作
    from sklearn import datasetsimport pandas as pdboston = datasets.load_boston()df = pd.DataFrame(boston.data, columns=boston.feature_names)1. []
  • pandas 篩選數據的 8 個神操作
    from sklearn import datasetsimport pandas as pdboston = datasets.load_boston()df = pd.DataFrame(boston.data, columns=boston.feature_names)1. []
  • Pandas - 操作CSV 文件
    CSV(Comma-Separated Values,逗號分隔值,有時也稱為字符分隔值,因為分隔字符也可以不是逗號),其文件以純文本形式存儲表格數據
  • Pandas 數據結構 - Series
    Pandas Series 類似表格中的一個列(column),類似於一維數組,可以保存任何數據類型。
  • 一日二技:Pandas 與 Docker 的使用技巧
    pandas 讀取無頭 CSV我們知道,CSV 一般是長這樣的:
  • 這是 Pandas 最詳細教程了
    pandas 最有趣的地方在於裡面隱藏了很多包。它是一個核心包,裡面有很多其他包的功能。這點很棒,因為你只需要使用 pandas 就可以完成工作。pandas 相當於 python 中 excel:它使用表(也就是 dataframe),能在數據上做各種變換,但還有其他很多功能。
  • Laid-back pandas ease into new home
    The two pandas - 4-year-old female Meng Meng and 7-year-old male Jiao Qing - arrived in the German capital last month.
  • Six pandas transferred from Wolong center
    A total of six pandas were taken away on Friday from a major panda base in Wolong of southwest China's Sichuan Province because of damaged shelters and food shortage after
  • 【pandas 基礎】
    構建的含有更高級數據結構和工具的數據分析包類似於 Numpy 的核心是 ndarray,pandas 也是圍繞著 Series 和 DataFrame 兩個核心數據結構展開的 。pandas 約定俗成的導入方法如下:lang:pythonfrom pandas import Series,DataFrameimport pandas as pd<br />SeriesSeries 可以看做一個定長的有序字典。
  • 數據分析利器 pandas 系列教程(二):強大的 DataFrame
    在上一篇文章 數據分析利器 pandas 系列教程(一):從 Series 說起  中:詳細介紹了 pandas 基礎數據結構 Series,今天說說另一種數據結構 DataFrame。通過列創建import pandas as pd#沒有設置行索引 index,取默認值df = pd.DataFrame({'name':['Bob','Alice','Joe']*3,               'sex':['male','female','male']*3,               'course':['math','english
  • 史上最全Pandas 教程!
    pandas 最有趣的地方在於裡面隱藏了很多包。它是一個核心包,裡面有很多其他包的功能。這點很棒,因為你只需要使用 pandas 就可以完成工作。pandas 相當於 python 中 excel:它使用表(也就是 dataframe),能在數據上做各種變換,但還有其他很多功能。如果你早已熟知 python 的使用,可以直接跳到第三段。