r - pandas 中的向量化按列正则表达式匹配
问题描述
第一部分
假设我有一个数据集 df,如下所示:
x | y
----|--------
foo | 1.foo-ya
bar | 2.bar-ga
baz | 3.ha-baz
qux | None
我想过滤 y 正好在中间包含 x 的行(不是开始也不是结束,即匹配模式 '^.+\w+.+$',命中第 1 行和第 2 行),不包括 None/NaN:
x | y
----|-----
foo | 1.foo-ya
bar | 2.bar-ga
这是一个典型的成对字符比较,在 SQL 中很容易:
select x, y from df where y like concat('^.+', x, '.+%');
或在 R 中:
library(dplyr)
library(stringr)
library(glue)
df %>% filter(str_detect(y, glue('^.+{x}.+$')))
但由于我不是熊猫专家,熊猫中似乎没有类似的简单“矢量化”正则表达式匹配方法?我应用了 lambda 方法:
import pandas as pd
import re
df.loc[df.apply(lambda row: bool(re.search(
'^.+' + row.x + '.+$', row.y))
if row.x and row.y else False, axis=1), :]
pandas 中有没有更优雅的方法来完成它?
第二部分
此外,我想在第一部分产生的匹配记录中提取前导数字 (1, 2, ...):
x | y | z
----|----------|---
foo | 1.foo-ya | 1
bar | 2.bar-ga | 2
在 R 中,我可以直接进行管道争吵:
df %>%
filter(str_detect(y, glue('^.+{x}.+$'))) %>%
mutate(z=str_replace(y, glue('^(\\d+)\\.{x}.+$'), '\\1') %>%
as.numeric)
但在熊猫中,我只知道 lambda 方法。有没有比它“更好”的方法?
a = df.loc[df.apply(lambda row: bool(
re.search('^.+' + row.x + '.+$', row.y))
if row.x and row.y else False, axis=1),
['x', 'y']]
a['z'] = a.apply(lambda row: re.sub(
r'^(\d+)\.' + row.x + '.+$', r'\1', row.y), axis=1).astype('int')
a
顺便说一句,assign
方法不起作用。
df.loc[df.apply(lambda row: bool(re.search(
'^.+' + row.x + '.+$', row.y))
if row.x and row.y else False, axis=1),
['x', 'y']].assign(z=lambda row: re.sub(
r'^(\d+)\.' + row.x + '.+$', r'\1', row.y))
谢谢!
解决方案
pandas 字符串操作是建立在 python 的 string 和 re 模块之上的。试一试,看看它是否是你想要的:
import re
#find out if values in column x are in column y
#according to the pattern u wrote in the question
pattern = [re.match(fr'^.+{a}.+$',b)
for a,b
in zip(df.x.str.strip(),
df.y.str.strip())
]
match = [ent.group() if ent is not None else np.nan for ent in pattern]
#extract values for digit immediately preceding val in col x
ext = [re.search(fr'\d(?=\.{a})', b) for a,b in
zip(df.x.str.strip(),
df.y.str.strip())]
extract = [ent.group() if ent is not None else np.nan for ent in ext]
df['match'], df['extract'] = match, extract
x y match extract
1 foo 1.foo-ya 1.foo-ya 1
2 bar 2.bar-ga 2.bar-ga 2
3 baz 3.ha-baz NaN NaN
4 qux None NaN NaN
推荐阅读
- apache-spark - pyspark 数据框连接操作和写为 json 很慢
- c++ - 为什么我的 C++ 代码仍在运行?我看不出任何理由
- php - 将 Linux 发行版的版本号解析为 PHP 变量
- sql-server - 在 SQL 中将行转置为列
- fortran - 仅对特定数组索引求和
- mysql - mysql group_concat 评分切片问题
- android - 通过 Android Studio 创建 Flutter 应用程序时出现问题
- wordpress - WOOF 产品过滤器仅显示基于先前选择的选项
- c# - Entity Framework Core 5.0:确保两列不能具有相同的值
- python - 将 Django CreateView 表单提交给自身