這篇文章給大家分享的是有關pandas初學者容易犯的錯誤有哪些的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
第一個錯誤與實際使用Pandas完成某些任務有關。具體來說我們在實際處理表格的數據集都非常龐大。使用pandas的read_csv讀取大文件將是你最大的錯誤。
為什么?因為它太慢了!看看這個測試,我們加載TPS十月數據集,它有1M行和大約300個特性,占用了2.2GB的磁盤空間。
import pandas as pd %%time tps_october = pd.read_csv("data/train.csv") Wall time: 21.8 s
read_csv花了大約22秒。你可能會說22秒并不多。但是在一個項目中,需要在不同的階段執行許多實驗。我們會創建很多單獨的腳本,用于清理、特征工程、選擇模型,以及其他任務。多次等待數據加載20秒就變得很長了。此外,數據集可能會更大時間就會更長。那么有什么更快的解決方案呢?
解決方案是在這個階段放棄Pandas,使用其他為快速IO設計的替代方案。我最喜歡的是datatable,但你也可以選擇Dask, Vaex, cuDF等。這里是用datatable加載相同的數據集所需要的時間:
import datatable as dt # pip install datatble %%time tps_dt_october = dt.fread("data/train.csv").to_pandas() ------------------------------------------------------------ Wall time: 2 s
只有2秒,10倍差距
函數式編程中最重要的規則之一就是永遠不要使用循環。似乎在使用 Pandas 時堅持這個“無循環”規則是加速計算的最佳方法。
函數式編程用遞歸代替循環。雖然遞歸也會出現各種問題(這個我們這里不考慮),但是對于科學計算來說使用矢量化是最好的選擇!
矢量化是 Pandas 和 NumPy 的核心,它對整個數組而不是單個標量執行數學運算。 Pandas 已經擁有一套廣泛的矢量化函數,我們無需重新發明輪子,只要關注我們的重點如何計算就好了。
在 Pandas 中進行Python 的大部分算術運算符(+、-、*、/、**)都以矢量化方式工作。此外,在 Pandas 或 NumPy 中看到的任何其他數學函數都已經矢量化了。
為了驗證到速度的提高,我們將使用下面的 big_function,它以三列作為輸入并執行一些無意義的算術作為測試:
def big_function(col1, col2, col3): return np.log(col1 ** 10 / col2 ** 9 + np.sqrt(col3 ** 3))
首先,我們將這個函數與 Pandas 最快的迭代器——apply 一起使用:
%time tps_october['f1000'] = tps_october.apply( lambda row: big_function(row['f0'], row['f1'], row['f2']), axis=1 ) ------------------------------------------------- Wall time: 20.1 s
操作耗時20秒。 讓我們以矢量化的方式使用核心 NumPy 數組來做同樣的事情:
%time tps_october['f1001'] = big_function(tps_october['f0'].values, tps_october['f1'].values, tps_october['f2'].values) ------------------------------------------------------------------ Wall time: 82 ms
只用了 82 毫秒,快了大約 250 倍。
事實上我們不能完全拋棄循環。 因為并非所有數據操作操作都是數學運算。 但是每當發現需要使用一些循環函數(例如 apply、applymap 或 itertuples)時,花點時間看看想要做的事情是否可以矢量化是一個非常好的習慣。
我們可以根據內存使用情況指定數據類型。
pandas中最糟糕也是最耗內存的數據類型是 object,這也恰好限制了 Pandas 的一些功能。 剩下的我們還有浮點數和整數。 以下這張表是pandas的所有類型:
Pandas命名方式中,數據類型名稱之后的數字表示此數據類型中的每個數字將占用多少位內存。 因此,我們的想法是將數據集中的每一列都轉換為盡可能小的子類型。 我們只要根據規則來判斷就可以了,這是規則表:
通常,根據上表將浮點數轉換為 float16/32 并將具有正整數和負整數的列轉換為 int8/16/32。 還可以將 uint8 用于布爾值和僅正整數,以進一步減少內存消耗。
這個函數你一定很眼熟,因為他在Kaggle中被廣泛使用,它根據上表將浮點數和整數轉換為它們的最小子類型:
def reduce_memory_usage(df, verbose=True): numerics = ["int8", "int16", "int32", "int64", "float16", "float32", "float64"] start_mem = df.memory_usage().sum() / 1024 ** 2 for col in df.columns: col_type = df[col].dtypes if col_type in numerics: c_min = df[col].min() c_max = df[col].max() if str(col_type)[:3] == "int": if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max: df[col] = df[col].astype(np.int8) elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max: df[col] = df[col].astype(np.int16) elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max: df[col] = df[col].astype(np.int32) elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max: df[col] = df[col].astype(np.int64) else: if ( c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max ): df[col] = df[col].astype(np.float16) elif ( c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max ): df[col] = df[col].astype(np.float32) else: df[col] = df[col].astype(np.float64) end_mem = df.memory_usage().sum() / 1024 ** 2 if verbose: print( "Mem. usage decreased to {:.2f} Mb ({:.1f}% reduction)".format( end_mem, 100 * (start_mem - end_mem) / start_mem ) ) return df
讓我們在 TPS 十月份的數據上使用它,看看我們能減少多少:
>>> reduce_memory_usage(tps_october) Mem. usage decreased to 509.26 Mb (76.9% reduction)
我們將數據集從原來的 2.2GB 壓縮到 510MB。當我們將df保存到csv文件時,這種內存消耗的減少會丟失因為csv還是以字符串的形式保存的,但是如果使用pickle保存那就沒問題了。
為什么要減小內存占用呢? 在使用大型機器學習模型處理此類數據集時,內存的占用和消耗起著重要作用。 一旦遇到一些 OutOfMemory 錯誤,你就會開始追趕并學習這樣的技巧來讓計算機保持愉快的工作(誰讓Kaggle只給16G的內存呢,都是逼出來的)。
Pandas 最美妙的功能之一是它能夠在顯示DF時設定不同的樣式,在 Jupyter 中將原始DF呈現為帶有一些 CSS HTML 表格。
Pandas 允許通過 style 屬性對其 DataFrame 進行樣式設置。
tps_october.sample(20, axis=1).describe().T.style.bar( subset=["mean"], color="#205ff2" ).background_gradient(subset=["std"], cmap="Reds").background_gradient( subset=["50%"], cmap="coolwarm" )
我們隨機選擇 20 列,為它們創建一個 5 位數的匯總,并轉置結果,根據它們的大小為均值、標準差和中值列著色。添加這樣的樣式可以讓我們更輕松地發現原始數字中的模式,設置無需使用其他的可視化庫。
實際上,不對df進行樣式設置并沒有錯。 但是這的確是一個很好的功能,對吧。
就像讀取 CSV 文件非常慢一樣,將數據保存回它們也是如此。 以下是將 TPS 十月數據保存到 CSV 所需的時間:
%%time tps_october.to_csv("data/copy.csv") ------------------------------------------ Wall time: 2min 43s
花了將近3分鐘。 為了節省時間可以保存為parquet,feather 甚至pickle。
%%time tps_october.to_feather("data/copy.feather") Wall time: 1.05 s -------------------------------------------------------------------------------- %%time tps_october.to_parquet("data/copy.parquet") Wall time: 7.84 s
實際上,這個對我來說最嚴重的錯誤是沒有閱讀Pandas 的文檔。但是一般情況下沒人會閱讀文檔,對吧。有時候 我們寧愿在互聯網上搜索數小時也不愿閱讀文檔。
但是當涉及到 Pandas 時,這個就是一個非常大的錯誤了。因為它像sklearn一樣有一個出色的用戶指南,涵蓋從基礎知識到如何貢獻代碼,甚至是如何設置更漂亮的主題(也許可能就是因為太多了,所以沒人看)。
我今天提到的所有錯誤都可以在文檔中找到。 甚至在文檔的“大型數據集”部分會專門告訴你使用其他軟件包(如 Dask)來讀取大文件并遠離 Pandas。 其實如果我有時間從頭到尾閱讀用戶指南,我可能會提出 50 個新手錯誤,所以還是看看文檔吧。
感謝各位的閱讀!關于“pandas初學者容易犯的錯誤有哪些”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。