Pandas 篩選過濾千萬級別數據,教你一招

大家好,我是早起。

今天分享一個數據清洗小技巧,可以讓你在遇到 百萬、千萬級別數據 的時候遊刃有餘。

先來說說問題的背景

現在有一個 csv 格式的數據集,大概 2 千萬條 左右的樣子,存儲的是用戶的網絡交互數據,其中電話號碼作爲用戶的唯一標識

再來看看我們要做啥

首先我們需要針對這批用戶確定所屬運營商,其次根據交互數據對各運營商的用戶感知情況進行分析,最後給出各運營商的相應優化解決措施。

這個目標的第一部分:確定用戶歸屬運營商,正好可以用今天這個小技巧去解決。

判斷兩千萬個號碼中每個號碼歸屬的運營商,你應該首先會想到循環遍歷。

但是你如果真的挨個號碼去遍歷一次,你會發現讀一遍數據都需要好久,甚至可能會需要幾分鐘、十幾分鍾。

所以今天會用到 Pandas 中的矢量化操作,通過 isin 函數進行篩選過濾,完成上面這個任務 只需要一兩秒

矢量化操作

矢量化,有別於對每一個單獨的值(標量)進行操作,是 Pandas 底層支持的對於整個 Array 進行的操作,也是 Pandas 中執行的最快的方法。

這種操作適用於對某一列的全體數據進行普適的操作,即矢量化是對整個數組執行操作的過程。

矢量化操作適用於 Pandas 的 Dataframe,Series 對象

Pandas 對於常用的函數,例如求和、平均值等常用統計函數做了非常好的矢量化支持。

在大多數場景下,我們需要做的只是 把一整列的元素,當成一個元素去處理,Pandas 會自動把函數應用到每一個單元格上。例如

df_data['age'] = df_data['age'] + 5

這就是最簡單的矢量化操作,就算你的數據集是 2 千萬條,執行一次簡單矢量化操作最多幾秒也就可以搞定。

isin 方法可以通過矢量化操作,完成簡單的數據篩選

isin 函數

常用的是 DataFrame 的 isin 函數,它的官方定義是這樣的:

def isin(self, values):
    """
    Whether each element in the DataFrame is contained in values.

 Parameters
    ----------
    values : iterable, Series, DataFrame or dict
    The result will only be true at a location if all the
    labels match. If `values` is a Series, that's the index. If
    `values` is a dict, the keys must be the column names,
    which must match. If `values` is a DataFrame,
    then both the index and column labels must match.

 Returns
    -------
    DataFrame
    DataFrame of booleans showing whether each element in the DataFrame
    is contained in values.
    """

可以看到需要傳入一個參數 values,函數會返回一個 DataFrame。

其中參數 values 大致解釋如下:

values :iterable, Series, DataFrame 或 dict

返回值是一個布爾的 DataFrame,顯示 DataFrame 中的每個元素是否包含在值 values 中。

大致解釋一下:

"""創建 DataFrame"""
df = pd.DataFrame({'num_legs'[2, 4]'num_wings'[2, 0]}index=['falcon''dog'])
df
           num_legs  num_wings
falcon         2          2
dog            4          0

# values 是列表
df.isin([0, 2])
          num_legs  num_wings
falcon      True       True
dog        False       True

# values 是 dict
df.isin({'num_wings'[0, 3]})
          num_legs  num_wings
falcon     False      False
dog        False       True

# values 是 DataFrame
other = pd.DataFrame({'num_legs'[8, 2]'num_wings'[0, 2]}index=['spider','falcon'])
df.isin(other)
          num_legs  num_wings
falcon      True       True
dog        False      False

isin 函數的用法就這些,很簡單,下面針對我們遇到的問題試試用 isin 快速解決

isin 實戰

首先在判斷號碼歸屬運營商時需要藉助一個表

對!各運營商對應的號段表

這個號段在網上應該都能查到,另外,需要注意還有一些運營商對應的虛擬號段

【各運營商號段】

根據號段去確定每個用戶號碼的運營商歸屬即可

具體實現代碼如下:

# 獲取移動運營商的號段
mobile_list = df_data.loc[df_data['運營商'] == '移動''號段'].drop_duplicates().tolist()
# 根據移動號段匹配所有移動用戶
df_data_mobile = df_data.loc[df_data['號段'].str.slice(0, 3).isin(mobile_list), :]

# 獲取聯通運營商的號段
unicom_list = df_data.loc[df_data['運營商'] == '聯通''號段'].drop_duplicates().tolist()
# 根據聯通號段匹配所有聯通用戶
df_data_unicom = df_data.loc[df_data['號段'].str.slice(0, 3).isin(unicom_list), :]

# 匹配電信用戶
df_data_net = df_data.loc[~df_data['號段'].str.slice(0, 3).isin(mobile_list) &
                          ~df_data['號段'].str.slice(0, 3).isin(unicom_list)
                          , :]

代碼中通過 isin 方法和 loc 結合,實現了對 DataFrame 的過濾篩選。

稍微解釋一下:首先根據移動號段確定移動用戶,其次根據聯通號段確定聯通用戶,最後通過 isin 的反方法確定非移動和聯通的號段,即電信號段,確定電信用戶。

需要注意,isin 方法的反方法是在其前面加上 ~,不存在 isnotin 方法,

寫在後面的話

巧用 isin 方法,可以極大的提高數據處理效率,還能提高打工人的代碼素養。

另外,類似的方法還有 where、cut 等,都可直接進行矢量化操作,下次遇到具體案例了再分享。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/w49WK2t6_Mqf2R6SPYP1Jw