In [1]: import pandas as pd
本教學課程使用資料
  • 本教學課程使用以 CSV 儲存的鐵達尼號資料集。資料包含下列資料欄

    • PassengerId:每位乘客的 ID。

    • Survived:表示乘客是否生還。是為 0,否為 1

    • Pclass:三種票艙等級之一:頭等艙 1、二等艙 2 和三等艙 3

    • Name:乘客姓名。

    • Sex:乘客性別。

    • Age:乘客年齡(以年為單位)。

    • SibSp:船上兄弟姊妹或配偶人數。

    • Parch:船上父母或子女人數。

    • Ticket:乘客票號。

    • Fare:表示票價。

    • Cabin:乘客艙房號碼。

    • Embarked:登船港口。

    至原始資料
    In [2]: titanic = pd.read_csv("data/titanic.csv")
    
    In [3]: titanic.head()
    Out[3]: 
       PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
    0            1         0       3  ...   7.2500   NaN         S
    1            2         1       1  ...  71.2833   C85         C
    2            3         1       3  ...   7.9250   NaN         S
    3            4         1       1  ...  53.1000  C123         S
    4            5         0       3  ...   8.0500   NaN         S
    
    [5 rows x 12 columns]
    

如何處理文字資料#

  • 將所有姓名字元轉為小寫。

    In [4]: titanic["Name"].str.lower()
    Out[4]: 
    0                                braund, mr. owen harris
    1      cumings, mrs. john bradley (florence briggs th...
    2                                 heikkinen, miss. laina
    3           futrelle, mrs. jacques heath (lily may peel)
    4                               allen, mr. william henry
                                 ...                        
    886                                montvila, rev. juozas
    887                         graham, miss. margaret edith
    888             johnston, miss. catherine helen "carrie"
    889                                behr, mr. karl howell
    890                                  dooley, mr. patrick
    Name: Name, Length: 891, dtype: object
    

    若要將 Name 欄中的每個字串轉為小寫,請選取 Name 欄(請參閱資料選取教學課程),加入 str 存取器,並套用 lower 方法。如此一來,每個字串都會逐一轉換。

類似於 時間序列教學 中具有 dt 存取器的日期時間物件,在使用 str 存取器時,有許多專門的字串方法可用。這些方法通常與單一元素的內建字串方法具有匹配的名稱,但會對每個欄位的數值逐一元素套用(還記得 逐一元素計算 嗎?)。

  • 建立一個新的欄位 Surname,其中包含乘客的姓氏,方法是擷取逗號之前的部分。

    In [5]: titanic["Name"].str.split(",")
    Out[5]: 
    0                             [Braund,  Mr. Owen Harris]
    1      [Cumings,  Mrs. John Bradley (Florence Briggs ...
    2                              [Heikkinen,  Miss. Laina]
    3        [Futrelle,  Mrs. Jacques Heath (Lily May Peel)]
    4                            [Allen,  Mr. William Henry]
                                 ...                        
    886                             [Montvila,  Rev. Juozas]
    887                      [Graham,  Miss. Margaret Edith]
    888          [Johnston,  Miss. Catherine Helen "Carrie"]
    889                             [Behr,  Mr. Karl Howell]
    890                               [Dooley,  Mr. Patrick]
    Name: Name, Length: 891, dtype: object
    

    使用 Series.str.split() 方法,每個數值會以 2 個元素的清單形式傳回。第一個元素是逗號之前的部分,第二個元素是逗號之後的部分。

    In [6]: titanic["Surname"] = titanic["Name"].str.split(",").str.get(0)
    
    In [7]: titanic["Surname"]
    Out[7]: 
    0         Braund
    1        Cumings
    2      Heikkinen
    3       Futrelle
    4          Allen
             ...    
    886     Montvila
    887       Graham
    888     Johnston
    889         Behr
    890       Dooley
    Name: Surname, Length: 891, dtype: object
    

    由於我們只對代表姓氏的第一個部分(元素 0)有興趣,因此我們可以再次使用 str 存取器並套用 Series.str.get() 來擷取相關部分。的確,這些字串函數可以串接,一次結合多個函數!

至使用者指南

使用者指南的 分割和取代字串 部分提供了更多關於擷取字串部分的資訊。

  • 擷取鐵達尼號上伯爵夫人的乘客資料。

    In [8]: titanic["Name"].str.contains("Countess")
    Out[8]: 
    0      False
    1      False
    2      False
    3      False
    4      False
           ...  
    886    False
    887    False
    888    False
    889    False
    890    False
    Name: Name, Length: 891, dtype: bool
    
    In [9]: titanic[titanic["Name"].str.contains("Countess")]
    Out[9]: 
         PassengerId  Survived  Pclass  ... Cabin Embarked  Surname
    759          760         1       1  ...   B77        S   Rothes
    
    [1 rows x 13 columns]
    

    有興趣了解她的故事嗎?請參閱 Wikipedia

    字串方法 Series.str.contains() 檢查欄位 Name 中的每個值,判斷字串是否包含字詞 Countess,並為每個值傳回 TrueCountess 是名稱的一部分)或 FalseCountess 不是名稱的一部分)。此輸出可搭配 資料子集教學 中介紹的條件(布林)索引,用於子選資料。由於鐵達尼號上只有一位女伯爵,因此我們只得到一列結果。

注意

字串中支援更強大的擷取,因為 Series.str.contains()Series.str.extract() 方法接受 正規表示式,但不在本教學範圍內。

至使用者指南

有關擷取字串部分的更多資訊,請參閱使用者指南中 字串比對和擷取 部分。

  • 鐵達尼號上哪位乘客的名字最長?

    In [10]: titanic["Name"].str.len()
    Out[10]: 
    0      23
    1      51
    2      22
    3      44
    4      24
           ..
    886    21
    887    28
    888    40
    889    21
    890    19
    Name: Name, Length: 891, dtype: int64
    

    要取得最長的名稱,我們首先必須取得 Name 欄位中每個名稱的長度。使用 pandas 字串方法,Series.str.len() 函式會個別套用至每個名稱(逐元素)。

    In [11]: titanic["Name"].str.len().idxmax()
    Out[11]: 307
    

    接下來,我們需要取得對應位置,最好是表格中名稱長度最長的索引標籤。 idxmax() 方法正是如此。它不是字串方法,而是套用於整數,因此不會使用 str

    In [12]: titanic.loc[titanic["Name"].str.len().idxmax(), "Name"]
    Out[12]: 'Penasco y Castellana, Mrs. Victor de Satode (Maria Josefa Perez de Soto y Vallejo)'
    

    根據列的索引名稱(307)和欄位(Name),我們可以使用 loc 算子進行選取,子集教學 中有介紹。

  • 在「性別」欄位中,將「男性」值取代為「M」,將「女性」值取代為「F」。

    In [13]: titanic["Sex_short"] = titanic["Sex"].replace({"male": "M", "female": "F"})
    
    In [14]: titanic["Sex_short"]
    Out[14]: 
    0      M
    1      F
    2      F
    3      F
    4      M
          ..
    886    M
    887    F
    888    F
    889    M
    890    M
    Name: Sex_short, Length: 891, dtype: object
    

    雖然 replace() 不是字串方法,但它提供一種便利的方式,可以使用對應或詞彙來轉換特定值。它需要一個 dictionary 來定義對應 {from : to}

警告

還有一個 replace() 方法可用來取代特定字元組。然而,當有多個值的對應時,這將會變成

titanic["Sex_short"] = titanic["Sex"].str.replace("female", "F")
titanic["Sex_short"] = titanic["Sex_short"].str.replace("male", "M")

這將會變得繁瑣且容易導致錯誤。只要想想(或自己嘗試)如果這兩個陳述套用順序相反會發生什麼事…

請記住

  • 字串方法可以使用 str 存取器。

  • 字串方法以元素為單位運作,可用於條件索引。

  • replace 方法是一個方便的方法,可以根據給定的字典轉換值。

至使用者指南

處理文字資料 的使用者指南頁面中提供了完整的概觀。