使用熊猫根据正则表达式分离列数据
Posted
技术标签:
【中文标题】使用熊猫根据正则表达式分离列数据【英文标题】:Segregate a column data based on regex using pandas 【发布时间】:2021-07-09 10:34:56 【问题描述】:我有一个如下所示的数据框
df = pd.DataFrame('val': ['>1234','<>','<1000','<test','31sadj',123,43.21])
我想创建 3 个新列
val_num
- 将仅存储 NUMBER 值与符号一起出现,例如:1234(来自 >1234)和 1000(来自
val_str
- 将只存储NUMBER
、symbols
、ALPHABETS
的混合值,或者只是简单的字母,例如:31sadj。它可以有除>
,<
,=
以外的任何符号
val_symbol
- 将仅存储 3 个符号,例如 >
、<
、=
我尝试了以下但不准确
df['val_SYMBOL'] = df['val'].str.extract(r'([<>=]+)').fillna('=')
df['val_num'] = df['val'].str.extract(r'([0-9]+)')
df['val_str'] = df['val'].str.extract(r'([a-zA-Z0-9\s-]+)')
我希望我的输出如下所示
【问题讨论】:
那么什么不好呢?我看到df['val'].str.extract(r'([<>=]+)').fillna('=')
工作正常。
另外两个 clumns 正则表达式不能正常工作
【参考方案1】:
你可以使用
df['val_SYMBOL'] = df['val'].astype(str).str.extract(r'([<>=]+)').fillna('=')
df['val_num'] = df['val'].astype(str).str.extract(r'\b(\d+(?:\.\d+)?)\b')
df['val_str'] = df['val'].astype(str).str.extract(r'([^<>=]*[a-zA-Z][^<>=]*)')
您要处理混合数据类型的列,因此第一个操作是将数据转换为带有astype(str)
的字符串。
val_num
列填充了 \b(\d+(?:\.\d+)?)\b
匹配项,整数或浮点数匹配为整个单词(\b
代表单词边界)。
val_str
列填充有 ([^<>=]*[a-zA-Z][^<>=]*)
匹配项,用于搜索除 <
、>
和 =
之外的零个或多个字符,然后是一个字母,然后是除 @ 之外的零个或多个字符987654331@、>
和 =
。
我得到的输出:
>>> df
val val_SYMBOL val_num val_str
0 >1234 > 1234 NaN
1 <> <> NaN NaN
2 <1000 < 1000 NaN
3 <test < NaN test
4 31sadj = NaN 31sadj
5 123 = 123 NaN
6 43.21 = 43.21 NaN
【讨论】:
【参考方案2】:Series.str.extract
我们可以将extract
与包含三个捕获组的正则表达式模式一起使用。
df['val'].astype(str).str.extract(
r'([<>=]+)?((?<=[<>=])\d+\.?\d*|\d+\.?\d*(?=$))?(.+)?').fillna(0: '=')
0 1 2
0 > 1234 NaN
1 <> NaN NaN
2 < 1000 NaN
3 < NaN test
4 = NaN 31sadj
5 = 123 NaN
6 = 43.21 NaN
正则表达式详细信息
([<>=]+)?
: 第一个捕获组匹配零次或一次
[<>=]+
:匹配列表中的一个或多个字符 [<>=]
((?<=[<>=])\d+\.?\d*|\d+\.?\d*(?=$))?
: : 第二个捕获组匹配零次或一次
(?<=[<>=])\d+\.?\d*
: 第一种选择
(?<=[<>=])\d+\.?\d*
:匹配列表中出现的符号之后的数字 [<>=]
\d+\.?\d*(?=$)
:第二个替代匹配行尾的数字
(.+)?
: 第三个捕获组匹配匹配零次或一次
.+
:匹配任意字符一次或多次。
See the online regex demo
【讨论】:
以上是关于使用熊猫根据正则表达式分离列数据的主要内容,如果未能解决你的问题,请参考以下文章