<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Pandas 新手容易犯的 6 個錯誤

          共 9854字,需瀏覽 20分鐘

           ·

          2022-06-29 12:40

          推薦關(guān)注↓


          我們在這里討論6個新手容易犯的錯誤,這些錯誤與你所使用工具的API或語法無關(guān),而是與你的知識和經(jīng)驗(yàn)水平直接相關(guān)。在實(shí)際中如果出現(xiàn)了這些問題可能不會有任何的錯

          誤提示,但是在應(yīng)用中卻會給我們帶來很大的麻煩。


          01
          使用Pandas自帶的函數(shù)讀取文件
          第一個錯誤與實(shí)際使用Pandas完成某些任務(wù)有關(guān)。具體來說我們在實(shí)際處理表格的數(shù)據(jù)集都非常龐大。使用pandas的read_csv讀取大文件將是你最大的錯誤。
          為什么?因?yàn)樗?看看這個測試,我們加載TPS十月數(shù)據(jù)集,它有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秒并不多。但是在一個項(xiàng)目中,需要在不同的階段執(zhí)行許多實(shí)驗(yàn)。我們會創(chuàng)建很多單獨(dú)的腳本,用于清理、特征工程、選擇模型,以及其他任務(wù)。多次等待數(shù)據(jù)加載20秒就變得很長了。此外,數(shù)據(jù)集可能會更大時間就會更長。那么有什么更快的解決方案呢?

          解決方案是在這個階段放棄Pandas,使用其他為快速IO設(shè)計(jì)的替代方案。我最喜歡的是datatable,但你也可以選擇Dask, Vaex, cuDF等。這里是用datatable加載相同的數(shù)據(jù)集所需要的時間:

          import datatable as dt  # pip install datatble

          %%time

          tps_dt_october = dt.fread("data/train.csv").to_pandas()

          ------------------------------------------------------------

          Wall time: 2 s

          只有2秒,10倍差距


          02
          沒有矢量化

          函數(shù)式編程中最重要的規(guī)則之一就是永遠(yuǎn)不要使用循環(huán)。似乎在使用 Pandas 時堅(jiān)持這個“無循環(huán)”規(guī)則是加速計(jì)算的最佳方法。

          函數(shù)式編程用遞歸代替循環(huán)。雖然遞歸也會出現(xiàn)各種問題(這個我們這里不考慮),但是對于科學(xué)計(jì)算來說使用矢量化是最好的選擇!

          矢量化是 Pandas 和 NumPy 的核心,它對整個數(shù)組而不是單個標(biāo)量執(zhí)行數(shù)學(xué)運(yùn)算。Pandas 已經(jīng)擁有一套廣泛的矢量化函數(shù),我們無需重新發(fā)明輪子,只要關(guān)注我們的重點(diǎn)如何計(jì)算就好了。

          在 Pandas 中進(jìn)行Python 的大部分算術(shù)運(yùn)算符(+、-、*、/、**)都以矢量化方式工作。此外,在 Pandas 或 NumPy 中看到的任何其他數(shù)學(xué)函數(shù)都已經(jīng)矢量化了。

          為了驗(yàn)證到速度的提高,我們將使用下面的 big_function,它以三列作為輸入并執(zhí)行一些無意義的算術(shù)作為測試:

          def big_function(col1, col2, col3):
              return np.log(col1 ** 10 / col2 ** 9 + np.sqrt(col3 ** 3))

          首先,我們將這個函數(shù)與 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 數(shù)組來做同樣的事情:

          %time tps_october['f1001'] = big_function(tps_october['f0'].values, 
                                                    tps_october['f1'].values, 
                                                    tps_october['f2'].values)

          ------------------------------------------------------------------

          Wall time: 82 ms

          只用了 82 毫秒,快了大約 250 倍。

          事實(shí)上我們不能完全拋棄循環(huán)。因?yàn)椴⒎撬袛?shù)據(jù)操作操作都是數(shù)學(xué)運(yùn)算。但是每當(dāng)發(fā)現(xiàn)需要使用一些循環(huán)函數(shù)(例如 apply、applymap 或 itertuples)時,花點(diǎn)時間看看想要做的事情是否可以矢量化是一個非常好的習(xí)慣。


          03
          數(shù)據(jù)類型,dtypes

          我們可以根據(jù)內(nèi)存使用情況指定數(shù)據(jù)類型。

          pandas中最糟糕也是最耗內(nèi)存的數(shù)據(jù)類型是 object,這也恰好限制了 Pandas 的一些功能。剩下的我們還有浮點(diǎn)數(shù)和整數(shù)。以下這張表是pandas的所有類型:

          Pandas命名方式中,數(shù)據(jù)類型名稱之后的數(shù)字表示此數(shù)據(jù)類型中的每個數(shù)字將占用多少位內(nèi)存。因此,我們的想法是將數(shù)據(jù)集中的每一列都轉(zhuǎn)換為盡可能小的子類型。我們只要根據(jù)規(guī)則來判斷就可以了,這是規(guī)則表:

          通常,根據(jù)上表將浮點(diǎn)數(shù)轉(zhuǎn)換為 float16/32 并將具有正整數(shù)和負(fù)整數(shù)的列轉(zhuǎn)換為 int8/16/32。還可以將 uint8 用于布爾值和僅正整數(shù),以進(jìn)一步減少內(nèi)存消耗。

          這個函數(shù)你一定很眼熟,因?yàn)樗贙aggle中被廣泛使用,它根據(jù)上表將浮點(diǎn)數(shù)和整數(shù)轉(zhuǎn)換為它們的最小子類型:

          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 十月份的數(shù)據(jù)上使用它,看看我們能減少多少:

          >>> reduce_memory_usage(tps_october)
          Mem. usage decreased to 509.26 Mb (76.9% reduction)

          我們將數(shù)據(jù)集從原來的 2.2GB 壓縮到 510MB。當(dāng)我們將df保存到csv文件時,這種內(nèi)存消耗的減少會丟失因?yàn)閏sv還是以字符串的形式保存的,但是如果使用pickle保存那就沒問題了。

          為什么要減小內(nèi)存占用呢?在使用大型機(jī)器學(xué)習(xí)模型處理此類數(shù)據(jù)集時,內(nèi)存的占用和消耗起著重要作用。一旦遇到一些 OutOfMemory 錯誤,你就會開始追趕并學(xué)習(xí)這樣的技巧來讓計(jì)算機(jī)保持愉快的工作(誰讓Kaggle只給16G的內(nèi)存呢,都是逼出來的)。


          04
          不設(shè)置樣式

          Pandas 最美妙的功能之一是它能夠在顯示DF時設(shè)定不同的樣式,在 Jupyter 中將原始DF呈現(xiàn)為帶有一些 CSS HTML 表格。

          Pandas 允許通過 style 屬性對其 DataFrame 進(jìn)行樣式設(shè)置。

          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"
          )

          我們隨機(jī)選擇 20 列,為它們創(chuàng)建一個 5 位數(shù)的匯總,并轉(zhuǎn)置結(jié)果,根據(jù)它們的大小為均值、標(biāo)準(zhǔn)差和中值列著色。添加這樣的樣式可以讓我們更輕松地發(fā)現(xiàn)原始數(shù)字中的模式,設(shè)置無需使用其他的可視化庫。

          實(shí)際上,不對df進(jìn)行樣式設(shè)置并沒有錯。但是這的確是一個很好的功能,對吧。


          05
          使用CSV格式保存文件

          就像讀取 CSV 文件非常慢一樣,將數(shù)據(jù)保存回它們也是如此。以下是將 TPS 十月數(shù)據(jù)保存到 CSV 所需的時間:

          %%time

          tps_october.to_csv("data/copy.csv")

          ------------------------------------------

          Wall time: 2min 43s

          花了將近3分鐘。為了節(jié)省時間可以保存為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

          06
          不看文檔
          實(shí)際上,這個對我來說最嚴(yán)重的錯誤是沒有閱讀Pandas 的文檔。但是一般情況下沒人會閱讀文檔,對吧。有時候 我們寧愿在互聯(lián)網(wǎng)上搜索數(shù)小時也不愿閱讀文檔。
          但是當(dāng)涉及到 Pandas 時,這個就是一個非常大的錯誤了。因?yàn)樗駍klearn一樣有一個出色的用戶指南,涵蓋從基礎(chǔ)知識到如何貢獻(xiàn)代碼,甚至是如何設(shè)置更漂亮的主題(也許可能就是因?yàn)樘嗔耍詻]人看)。
          我今天提到的所有錯誤都可以在文檔中找到。甚至在文檔的“大型數(shù)據(jù)集”部分會專門告訴你使用其他軟件包(如 Dask)來讀取大文件并遠(yuǎn)離 Pandas。其實(shí)如果我有時間從頭到尾閱讀用戶指南,我可能會提出 50 個新手錯誤,所以還是看看文檔吧。

          07
          總結(jié)
          今天,我們學(xué)習(xí)了新手在使用Pandas時最常犯的六個錯誤。
          我們這里提到的錯誤大部分和大數(shù)據(jù)集有關(guān),只有當(dāng)使用GB大小的數(shù)據(jù)集時可能才會出現(xiàn)。如果你還在處理泰坦尼克這種新手?jǐn)?shù)據(jù)集,你可能都不會感覺到有這些問題。但是當(dāng)你開始處理真實(shí)世界的數(shù)據(jù)集時,這些概念會讓別人覺得你不是一個新手而是真正有過實(shí)際經(jīng)驗(yàn)的人。

          長按或掃描下方二維碼,后臺回復(fù):加群,即可申請入群。一定要備注:來源+研究方向+學(xué)校/公司,否則不拉入群中,見諒!

          長按三秒,進(jìn)入后臺


          推薦閱讀

          瀏覽 41
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩淫色电影 | 日本一道码高清无码 | 国产精品无码7777777 | 日韩黄色电影 | 国产视频黄色精频大全 |