The 查询()方法Pandas 中允许您根据查询表达式过滤 DataFrame 行。
将正则表达式 (regex) 的强大功能与query()
方法允许更高级和灵活的查询。
本教程将指导您完成使用正则表达式的过程query()
熊猫中的方法。
匹配字符串的开头或结尾
您可以使用以下字符来匹配字符串的开头或结尾:
-
^
: 代表字符串的开头。
-
$
: 表示字符串的结束。
匹配开头
首先,让我们创建一个示例 DataFrame:
import pandas as pd
data = {
'item_name': ['apple', 'banana', 'cherry', 'pineapple', 'apple pie', 'banana split']
}
df = pd.DataFrame(data)
让我们发现以子字符串“apple”开头的项目。
start_with_apple = df.query("item_name.str.contains('^apple')")
print(start_with_apple)
Output:
item_name
0 apple
4 apple pie
在这里,图案^apple
使用,确保仅选择那些以“apple”开头的项目。
匹配结尾
现在,要识别以“apple”结尾的项目。
end_with_apple = df.query("item_name.str.contains('apple$')")
print(end_with_apple)
Output:
item_name
0 apple
3 pineapple
这确保提取以“apple”结尾的项目。
基本正则表达式模式
正则表达式带有基本模式和元字符,可以增强您的文本匹配任务:
-
.
(Dot):匹配除换行符之外的任何单个字符。
-
*
(星号):匹配前面的字符或组的零次或多次重复。
让我们来说明一下这些模式。
# Query to find item names that contain exactly five characters
five_chars = df.query("item_name.str.contains('^.....$')")
print(five_chars)
Output:
item_name
0 apple
在这个查询中,.....
匹配字符串中任意位置包含五个字符的任何项目名称。
对于我们的下一个示例,让我们识别包含后跟“apple”的任何字符集的项目。
pattern_start = df.query("item_name.str.contains('.*apple')")
print(pattern_start)
Output:
item_name
0 apple
3 pineapple
4 apple pie
The .*
翻译为“零个或多个任何字符”。
字符类别和范围
使用方括号描述字符类[]
。例如,[abc]
将匹配“a”、“b”或“c”中的任何单个字符。
让我们识别包含字母“a”或“p”,后跟字母“i”的项目。
char_class_query = df.query("item_name.str.contains('[ap]i')")
print(char_class_query)
Output:
item_name
3 pineapple
4 apple pie
在此查询中,模式[ap]i
捕获名称中包含“ai”或“pi”的项目。
Ranges
范围是字符类的子集。您可以使用连字符指定范围,而不是列出单个字符。例如,[a-c]
将匹配任何单个字符“a”、“b”或“c”。
为了说明这一点,让我们提取名称中包含“a”和“c”之间的任何小写字母并后跟字母“e”的项目。
range_query = df.query("item_name.str.contains('[a-h]e')")
print(range_query)
Output:
item_name
2 cherry
图案[a-h]e
匹配包含“ae”、“be”、“ce”、“de”、“ee”、“fe”、“ge”和“he”等子字符串的项目。
根据某些模式排除行
结合使用字符类^
字符(方括号内)使您能够否定特定字符。
例如,如果您希望排除包含字母“a”或“p”的项目:
exclude_chars = df.query("not item_name.str.contains('[ap]')")
print(exclude_chars)
Output:
item_name
2 cherry
图案not item_name.str.contains('[ap]')
确保包含字母“a”或“p”的行从结果中排除。
排除特定模式
要根据特定模式排除行,请使用not
关键字与您的正则表达式模式一起在query()
method.
假设您要排除以“apple”结尾的项目:
exclude_pattern = df.query("not item_name.str.contains('apple$')")
print(exclude_pattern)
Output:
item_name
1 banana
2 cherry
4 apple pie
5 banana split
忽略正则表达式查询中的大小写敏感性
默认情况下,搜索将区分小写和大写字符。
要执行不区分大小写的搜索,可以使用 case 参数。
以下是如何以不区分大小写的方式搜索“apple”:
import re
case_insensitive_search = df.query('item_name.str.contains("APPLE", case=False)')
print(case_insensitive_search)
Output:
item_name
0 apple
3 pineapple
4 apple pie
使用上面的代码,搜索将匹配“apple”和“pineapple”(以及任何其他包含“apple”的字符串,无论大小写)。
正向和负向前瞻/后瞻
正向先行断言字符串中当前位置之后的内容,但不消耗任何字符。语法是(?=...)
.
查找后跟空格的文本
例如,要查找“apple”后跟一个空格的项目:
positive_lookahead_query = df.query("item_name.str.contains('apple(?= )')")
print(positive_lookahead_query)
Output:
item_name
4 apple pie
仅当模式“apple(?= )”后面直接跟有空格时,才与术语“apple”匹配。
查找后面没有空格的文本
语法是(?!...)
.
要查找带有“apple”且后面没有空格的项目:
negative_lookahead_query = df.query("item_name.str.contains('apple(?! )')")
print(negative_lookahead_query)
Output:
item_name
0 apple
3 pineapple
查找前面有空格的文本
正向回顾断言字符串中当前位置之前的内容,但同样不会消耗字符。语法是(?<=...)
.
要查找“pie”一词前面有空格的项目:
positive_lookbehind_query = df.query("item_name.str.contains('(?<= )pie')")
print(positive_lookbehind_query)
Output:
item_name
4 apple pie
仅当模式“(?
查找前面没有空格的文本
负向后查找断言某个字符串不直接位于当前位置之前。语法是(?<!...)
.
要查找“pie”前面没有空格的项目:
negative_lookbehind_query = df.query("item_name.str.contains('(?<! )pi')")
print(negative_lookbehind_query)
Output:
item_name
3 pineapple
在这种情况下,只有“pineapple”包含术语“pi”,前面没有空格。
基于具有特殊字符的模式进行过滤
匹配特殊字符,例如$.^*+?{}[]\()|
,您必须使用反斜杠“转义”它们\
.
例如,如果您想查找带有美元符号的项目$
:
import pandas as pd
data = {
'item_name': ['$apple', 'banana', 'cherry', 'pineapple', 'apple pie', 'banana split']
}
df = pd.DataFrame(data)
special_char_query = df.query("item_name.str.contains('\\$')")
print(special_char_query)
Output:
item_name
0 $apple
在这里,图案\\$
确保美元符号被视为文字字符,而不是代表字符串结尾的正则表达式元字符。
分组和捕获
正则表达式中的组是使用括号创建的(...)
。它们不仅将模式的元素组合在一起,而且还捕获与该组匹配的内容。
例如,要识别以“apple”开头,后跟任意字符序列的项目:
grouping_query = df.query("item_name.str.contains('^(apple)(.+)$')")
print(grouping_query)
Output:
item_name
4 apple pie
Here, ^(apple)(.+)$
有两组:(apple)
and (.+)
。第一组捕获“apple”一词,第二组捕获任何一个或多个字符。
从组中捕获内容
要提取特定的捕获内容,您通常会使用str.extract()
method:
captured_content = df['item_name'].str.extract('^(apple)(.*)$')
print(captured_content)
Output:
0 1
0 apple
1 NaN NaN
2 NaN NaN
3 NaN NaN
4 apple pie
5 NaN NaN
数据框captured_content
有两列,每列代表正则表达式模式中的一个捕获组。
具有匹配项的行显示捕获的内容,而其他行则显示 NaN。
非捕获组
在某些情况下,您希望对元素进行分组而不捕获匹配的内容。
这可以使用语法来完成(?:...)
.
例如,将“苹果”或“香蕉”分组但不捕获:
non_capturing_group_query = df.query("item_name.str.contains('^(?:apple|banana)')")
print(non_capturing_group_query)
Output:
item_name
0 apple
1 banana
4 apple pie
5 banana split
图案^(?:apple|banana)
将“苹果”和“香蕉”分组进行交替,但不捕获他们的比赛。
反向引用
反向引用表示为\n
where n
是与您所引用的捕获组对应的编号。例如,\1
指的是第一个捕获组。
为了进行演示,让我们查找具有重复单词的项目,例如“apple apple”:
import pandas as pd
data = {
'item_name': ['apple apple', 'banana', 'cherry', 'pineapple', 'apple pie', 'banana split']
}
df = pd.DataFrame(data)
backreference_query = df.query(r"item_name.str.contains('^(\\w+) \\1$')")
print(backreference_query)
Output:
item_name
0 apple apple
在图案中^(\\w+) \\1$
,第一组(\\w+)
捕获单词字符序列。
反向引用\\1
then 引用该组匹配的内容,确保相同的序列再次出现。