先初始化數據
import pandas as pd import numpy as np index = pd.Index(data=["Tom", "Bob", "Mary", "James", "Andy", "Alice"], name="name") data = { "age": [18, 30, np.nan, 40, np.nan, 30], "city": ["Bei Jing", "Shang Hai", "Guang Zhou", "Shen Zhen", np.nan, " "], "sex": [None, "male", "female", "male", np.nan, "unknown"], "birth": ["2000-02-10", "1988-10-17", None, "1978-08-08", np.nan, "1988-10-17"] } user_info = pd.DataFrame(data=data, index=index)
user_info["birth"] = pd.to_datetime(user_info.birth) user_info
為什么要用str屬性
文本數據也就是我們常說的字符串,Pandas 為 Series 提供了 str 屬性,通過它可以方便的對每個元素進行操作。在之前已經了解過,在對 Series 中每個元素處理時,我們可以使用 map 或 apply 方法。
# 將每個城市都轉為小寫: user_info.city.map(lambda x: x.lower())
What?竟然出錯了,錯誤原因是因為 float 類型的對象沒有 lower 屬性。這是因為缺失值 (np.nan)屬於float 類型
這時候我們的 str 屬性操作來了,來看看如何使用吧
# 將文本轉為小寫 user_info.city.str.lower() # 統計每個字符串的長度 user_info.city.str.len()
替換和分割
替換操作
# 將空字符串替換成下划線: user_info.city.str.replace(" ", "_") # 使用正則表達式將所有開頭為 S 的城市替換為空字符串: user_info.city.str.replace("^S.*", " ")
分割操作
# 根據空字符串來分割某一列: user_info.city.str.split(" ") """ name Tom [Bei, Jing] Bob [Shang, Hai] Mary [Guang, Zhou] James [Shen, Zhen] Andy NaN Alice [, ] Name: city, dtype: object """ #分割列表中的元素可以使用 get 或 [] 符號進行訪問: user_info.city.str.split(" ").str.get(0) """ name Tom Bei Bob Shang Mary Guang James Shen Andy NaN Alice Name: city, dtype: object """ user_info.city.str.split(" ").str[1] """ name Tom Jing Bob Hai Mary Zhou James Zhen Andy NaN Alice Name: city, dtype: object """ # 設置參數 expand=True 可以輕松擴展此項以返回 DataFrame user_info.city.str.split(" ", expand=True) """ 0 1 name Tom Bei Jing Bob Shang Hai Mary Guang Zhou James Shen Zhen Andy NaN NaN Alice """
提取子串
從一個長的字符串中提取出子串。
提取第一個匹配的子串
extract 只能夠匹配出第一個子串,extract 方法接受一個正則表達式並至少包含一個捕獲組,指定參數 expand=True 可以保證每次都返回 DataFrame。
\s+ :一個或多個空字符串
(\w+):分組捕獲任意多個字符
(\w+)\s+:在一個或多個空字符串前,分組捕獲任意多個字符
# 匹配空字符串前面的所有的字母 user_info.city.str.extract("(\w+)\s+", expand=True) """ 0 name Tom Bei Bob Shang Mary Guang James Shen Andy NaN Alice NaN """ # 如果使用多個組提取正則表達式會返回一個 DataFrame,每個組只有一列。 # 匹配出空字符串前面和后面的所有字母 user_info.city.str.extract("(\w+)\s+(\w+)", expand=True) """ 0 1 name Tom Bei Jing Bob Shang Hai Mary Guang Zhou James Shen Zhen Andy NaN NaN Alice NaN NaN """
匹配所有子串
extract 只能夠匹配出第一個子串,使用 extractall 可以匹配出所有的子串。
# 將所有組的空白字符串前面的字母都匹配出來 user_info.city.str.extractall("(\w+)\s+") """ 0 name match Tom 0 Bei Bob 0 Shang Mary 0 Guang James 0 Shen """
測試是否包含子串
使用 contains 來測試是否包含子串 --> 布爾值
# 測試城市是否包含子串 'Zh': user_info.city.str.contains("Zh") # 測試是否是以字母 'S' 開頭: user_info.city.str.contains("^S")
生成啞變量
這是一個神奇的功能,通過 get_dummies 方法可以將字符串轉為啞變量, sep 參數是指定啞變量之間的分隔符
user_info.city.str.get_dummies(sep=" ")
方法摘要
方法 | 描述 |
cat() | 連接字符串 |
split() | 在分隔符上分割字符串 |
rsplit() | 從字符串末尾開始分隔字符串 |
get() | 索引到每個元素(檢索第i個元素) |
join() | 使用分隔符在系列的每個元素中加入字符串 |
get_dummies() | 在分隔符上分割字符串,返回虛擬變量的DataFrame |
contains() | 如果每個字符串都包含pattern / regex,則返回布爾數組 |
replace() | 用其他字符串替換pattern / regex的出現 |
repeat() ) | 重復值(s.str.repeat(3)等同於x * 3 t2 ) |
pad() | 將空格添加到字符串的左側,右側或兩側 |
center() | 相當於str.center |
ljust() | 相當於str.ljust |
rjust() | 相當於str.rjust |
zfill() | 等同於str.zfill |
wrap() | 將長長的字符串拆分為長度小於給定寬度的行 |
slice() | 切分Series中的每個字符串 |
slice_replace() | 用傳遞的值替換每個字符串中的切片 |
count() | 計數模式的發生 |
startswith() | 相當於每個元素的str.startswith(pat) |
endswith() | 相當於每個元素的str.endswith(pat) |
findall() | 計算每個字符串的所有模式/正則表達式的列表 |
match() | 在每個元素上調用re.match,返回匹配的組作為列表 |
extract() | 在每個元素上調用re.search,為每個元素返回一行DataFrame,為每個正則表達式捕獲組返回一列 |
extractall() | 在每個元素上調用re.findall,為每個匹配返回一行DataFrame,為每個正則表達式捕獲組返回一列 |
len() | 計算字符串長度 |
normalize() | 返回Unicode標准格式。相當於unicodedata.normalize |