In [1]: import pandas as pd
Data used for this tutorial:
  • 本教程使用泰坦尼克号数据集,存储为CSV格式。数据包括以下数据列:

    • PassengerId: 每位乘客的ID。

    • 幸存:乘客是否幸存的指示。0 表示是,1 表示否。

    • Pclass:三种票等级之一:等级 1、等级 2 和等级 3

    • 姓名:乘客的姓名。

    • Sex: 乘客的性别。

    • 年龄:乘客的年龄(岁)。

    • SibSp: 同船的兄弟姐妹或配偶的数量。

    • Parch: 父母或孩子在船上的数量。

    • 票:乘客的票号。

    • 票价:指示票价。

    • Cabin: 乘客的舱位号。

    • Embarked: 登船港。

    To raw data
    In [2]: titanic = pd.read_csv("data/titanic.csv")
    
    In [3]: titanic.head()
    Out[3]: 
       PassengerId  Survived  Pclass                                               Name     Sex   Age  SibSp  Parch            Ticket     Fare Cabin Embarked
    0            1         0       3                            Braund, Mr. Owen Harris    male  22.0      1      0         A/5 21171   7.2500   NaN        S
    1            2         1       1  Cumings, Mrs. John Bradley (Florence Briggs Th...  female  38.0      1      0          PC 17599  71.2833   C85        C
    2            3         1       3                              Heikkinen, Miss Laina  female  26.0      0      0  STON/O2. 3101282   7.9250   NaN        S
    3            4         1       1       Futrelle, Mrs. Jacques Heath (Lily May Peel)  female  35.0      1      0            113803  53.1000  C123        S
    4            5         0       3                           Allen, Mr. William Henry    male  35.0      0      0            373450   8.0500   NaN        S
    

如何操作文本数据#

  • 将所有名称字符转换为小写。

    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 方法。这样,每个字符串都会逐元素转换。

类似于在 时间序列教程 中的 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() 来提取相关部分。实际上,这些字符串函数可以串联起来,一次性组合多个函数!

To user guide

更多关于提取字符串部分的信息,请参阅用户指南中关于 拆分和替换字符串 的部分。

  • 提取关于泰坦尼克号上女伯爵的乘客数据。

    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                                               Name     Sex   Age  SibSp  Parch  Ticket  Fare Cabin Embarked Surname
    759          760         1       1  Rothes, the Countess. of (Lucy Noel Martha Dye...  female  33.0      0      0  110152  86.5   B77        S  Rothes
    

    (对她的故事感兴趣吗?请看 Wikipedia)

    字符串方法 Series.str.contains() 检查列 Name 中的每个值是否包含单词 Countess ,并为每个值返回 TrueCountess 是名字的一部分)或 FalseCountess 不是名字的一部分)。此输出可用于使用条件(布尔)索引对数据进行子选择,这在 数据子集教程 中有介绍。由于泰坦尼克号上只有一位女伯爵,我们得到的结果是一行。

备注

更强大的字符串提取功能是支持的,因为 Series.str.contains()Series.str.extract() 方法接受 正则表达式 ,但这些内容超出了本教程的范围。

To user guide

更多关于提取字符串部分的信息可以在用户指南的 字符串匹配和提取 部分找到。

  • 泰坦尼克号上哪位乘客的名字最长?

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

这会变得繁琐且容易出错。只需想象(或亲自尝试)如果这两个声明以相反的顺序应用会发生什么…

REMEMBER

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

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

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

To user guide

在用户指南页面中提供了 处理文本数据 的完整概述。