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: str
    

    要将 Name 列中的每个字符串转换为小写,请选择 Name 列(参见 数据选择教程),添加 str 访问器并应用 lower 方法。这样,每个字符串都会逐个元素地进行转换。

时间序列教程 中的 datetime 对象拥有 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]
    

    (对她的故事感兴趣?请参见 维基百科)

    字符串方法 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      21
    3      44
    4      24
           ..
    886    21
    887    27
    888    39
    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 运算符进行选择。

  • 在“Sex”列中,将“male”替换为“M”,将“female”替换为“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: str
    

    虽然 replace() 不是字符串方法,但它提供了一种便捷的方式来使用映射或词汇表来翻译某些值。它需要一个 字典 来定义映射 {from: to}

警告

还有一个 replace() 方法可用于替换一组特定的字符。然而,当有一个多值映射时,这会变得

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

这样会很麻烦,而且很容易出错。想想(或自己尝试)如果这两个语句的顺序颠倒过来会发生什么……

请记住

  • 可以使用 str 访问器来使用字符串方法。

  • 字符串方法逐个元素工作,并可用于条件索引。

  • replace 方法是一种便捷的方法,可根据给定的字典转换值。

用户指南

完整的概述可在用户指南关于 处理文本数据 的页面中找到。