杰瑞科技汇

python dataframe文本

核心概念:.str 访问器

在 Pandas 中,当你需要对一列字符串进行操作时,不能直接使用 Python 内置的字符串方法(如 .upper().split() 等),你必须使用 Pandas 提供的 .str 访问器

python dataframe文本-图1
(图片来源网络,侵删)

.str 访问器将 Pandas 的 Series 对象包装起来,并提供了大量与字符串相关的方法,这些方法的行为与 Python 内置方法类似,但它们能够:

  • 自动处理缺失值 (NaN):不会因为 NaN 而报错。
  • 高效地向量化操作:在底层用 C 语言优化,比在循环中逐个处理字符串快得多。

基本语法:

import pandas as pd
import numpy as np
# 创建一个示例 DataFrame
data = {'name': ['Alice', 'Bob', 'Charlie', 'David', np.nan, 'Eve'],
        'city': ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix', 'Philadelphia']}
df = pd.DataFrame(data)
# 对 'name' 列进行操作
df['name_upper'] = df['name'].str.upper()
print(df)

输出:

      name           city   name_upper
0    Alice       New York       ALICE
1      Bob    Los Angeles         BOB
2  Charlie        Chicago     CHARLIE
3    David        Houston       DAVID
4      NaN        Phoenix          NaN
5      Eve  Philadelphia         EVE

注意,NaN 保持了原样,没有被报错。


常用 .str 方法详解

下面我们分类介绍最常用的一些 .str 方法。

1 基本修改方法

这些方法用于改变字符串的大小写或填充。

方法 描述 示例
.str.lower() 转换为小写 df['name'].str.lower()
.str.upper() 转换为大写 df['name'].str.upper()
.str.title() 格式 (每个单词首字母大写) df['city'].str.title()
.str.capitalize() 转换为字符串首字母大写 df['name'].str.capitalize()
.str.strip() 去除字符串两端的空白字符(空格、换行等) df['name'].str.strip()
.str.lstrip() 去除字符串左端的空白字符 df['name'].str.lstrip()
.str.rstrip() 去除字符串右端的空白字符 df['name'].str.rstrip()

示例:

df['city_clean'] = df['city'].str.strip().str.title()
print(df[['city', 'city_clean']])

2 拆分与连接

方法 描述 示例
.str.split() 拆分字符串,默认按空格拆分,返回一个列表 df['city'].str.split()
.str.split(pat=...) 按指定分隔符 pat 拆分 df['city'].str.split(pat=' ')
.str.get() 从拆分后的列表中获取指定索引的元素 df['city'].str.split().str.get(0) 获取城市名
.str.cat() 连接字符串,可以指定分隔符 sep df['name'].str.cat(df['city'], sep=' from ')

示例:

# 拆分城市名和州(假设数据中有州)
df['full_location'] = ['New York, NY', 'Los Angeles, CA', 'Chicago, IL', 'Houston, TX', 'Phoenix, AZ', 'Philadelphia, PA']
df['state'] = df['full_location'].str.split(', ').str.get(1)
df['city_only'] = df['full_location'].str.split(', ').str.get(0)
print(df[['full_location', 'city_only', 'state']])

3 替换与模式匹配

这是文本处理的核心,支持正则表达式。

方法 描述 示例
.str.replace() 替换字符串中的匹配项 df['name'].str.replace('a', '@')
.str.contains() 检查字符串是否包含某个子串,返回布尔值 df['city'].str.contains('New')
.str.startswith() 检查字符串是否以指定子串开头 df['city'].str.startswith('New')
.str.endswith() 检查字符串是否以指定子串结尾 df['city'].str.endswith('on')
.str.match() 检查字符串是否从头开始匹配正则表达式 df['city'].str.match('New.*')
.str.fullmatch() 检查字符串是否完全匹配正则表达式 df['city'].str.fullmatch('New York')
.str.extract() 从字符串中提取匹配正则表达式的第一个分组 df['full_location'].str.extract(r'(\w+), (\w+)')
.str.extractall() 提取所有匹配的分组 (较少用,通常用于多级索引)
.str.findall() 找到所有匹配正则表达式的子串,返回列表 df['full_location'].str.findall(r'\w+')

正则表达式 (re) 元字符备忘录:

  • : 任意字符
  • : 0次或多次
  • : 1次或多次
  • : 0次或1次
  • ^ : 字符串开头
  • : 字符串结尾
  • [] : 字符集,如 [a-z] 表示任意小写字母
  • : 分组,用于提取
  • \d : 数字
  • \w : 单词字符 (字母, 数字, 下划线)
  • \s : 空白字符

示例:

# 1. 替换
df['name_with_underscores'] = df['name'].str.replace('a', '_a_')
# 2. 检查包含
df['has_i'] = df['name'].str.contains('i') # 'i' 或 'I'
# 3. 提取州代码 (使用 extract)
# r'' 表示原始字符串,避免反斜杠转义
states = df['full_location'].str.extract(r', (\w{2})')
states.columns = ['state_code'] # 为提取的列命名
df = pd.concat([df, states], axis=1)
# 4. 使用正则表达式替换 (移除所有非字母字符)
df['name_cleaned'] = df['name'].str.replace('[^a-zA-Z]', '', regex=True)
print(df[['name', 'name_with_underscores', 'has_i', 'full_location', 'state_code', 'name_cleaned']])

4 长度与计数

方法 描述 示例
.str.len() 计算字符串的长度 df['name'].str.len()
.str.count() 计算子串在字符串中出现的次数 df['name'].str.count('a')

示例:

df['name_length'] = df['name'].str.len()
df['a_count'] = df['name'].str.count('a')
print(df[['name', 'name_length', 'a_count']])

实战案例:数据清洗

假设我们有一份包含用户评论的“脏”数据,需要进行清洗。

原始数据:

import pandas as pd
import numpy as np
data = {
    'id': [1, 2, 3, 4, 5],
    'review': [
        'This product is AMAZING!!!',
        'it is okay, not great.',
        'Worst purchase EVER. DO NOT BUY.',
        'Good value for money.',
        np.nan
    ]
}
reviews_df = pd.DataFrame(data)

清洗目标:

  1. 将所有文本转换为小写,以便进行统一分析。
  2. 去除标点符号(, 等)。
  3. NaN 值替换为字符串 'no review'

解决方案:

# 1. 转换为小写
reviews_df['review_clean'] = reviews_df['review'].str.lower()
# 2. 去除标点符号
# 使用正则表达式 [^a-zA-Z\s] 匹配所有非字母和非空格的字符
reviews_df['review_clean'] = reviews_df['review_clean'].str.replace('[^a-z\s]', '', regex=True)
# 3. 处理缺失值
# fillna() 可以填充 NaN,然后我们再对填充后的字符串进行处理
# 或者直接在 str 方法中处理,但更清晰的做法是先填充
reviews_df['review_clean'] = reviews_df['review_clean'].fillna('no review')
print(reviews_df)

输出:

   id                                           review review_clean
0   1                             This product is AMAZING!!!  this product is amazing
1   2                              it is okay not great.    it is okay not great
2   3                Worst purchase EVER DO NOT BUY.    worst purchase ever do not buy
3   4                               Good value for money.    good value for money
4   5                                                NaN            no review

进阶技巧

1 链式操作 (Method Chaining)

Pandas 的 .str 方法返回一个新的 Series,因此你可以将它们像链条一样连接起来,使代码更简洁、易读。

# 不使用链式操作
df['temp'] = df['review'].str.lower()
df['temp'] = df['temp'].str.replace('!', '')
df['temp'] = df['temp'].str.replace('.', '')
df['temp'] = df['temp'].str.replace(',', '')
# ... 这样很繁琐
# 使用链式操作
df['review_chained'] = (df['review']
                        .str.lower()
                        .str.replace('[^a-z\s]', '', regex=True) # 一次性替换所有非字母字符
                        .str.strip() # 最后再去除两端空格
                       )
print(df[['review', 'review_chained']])

2 结合 apply 和自定义函数

.str 提供的方法无法满足你的复杂需求时,你可以结合 apply 和一个自定义的 Python 函数。

注意: apply 会比纯 .str 方法慢,因为它在 Python 层面循环,只在必要时使用。

示例: 创建一个函数,判断评论是正面、负面还是中性。

def sentiment(text):
    if pd.isna(text):
        return 'neutral'
    text = text.lower()
    if 'amazing' in text or 'good' in text:
        return 'positive'
    elif 'worst' in text or 'bad' in text:
        return 'negative'
    else:
        return 'neutral'
# 使用 apply
reviews_df['sentiment'] = reviews_df['review'].apply(sentiment)
print(reviews_df[['review', 'sentiment']])

任务 推荐方法
大小写转换/去除空格 .str.lower(), .str.upper(), .str.strip()
拆分字符串 .str.split() + .str.get()
简单替换/检查 .str.replace(), .str.contains(), .str.startswith()
复杂模式匹配/提取 .str.extract(), .str.findall() (配合正则表达式)
计算长度/计数 .str.len(), .str.count()
复杂、多步骤清洗 链式操作 (df['col'].str.method1().str.method2())
高度自定义的逻辑 df['col'].apply(your_custom_function)

掌握 Pandas 的 .str 访问器是进行数据清洗和文本分析的关键技能,它高效、强大,并且能让你用简洁的代码完成复杂的文本处理任务。

分享:
扫描分享到社交APP
上一篇
下一篇