我有一个如下所示的数据框
df = pd.DataFrame({'val': ['>1234','<>','<1000','<test','31sadj',123,43.21]})
我想创建 3 个新列
val_num
- 将仅存储与符号一起出现的 NUMBER 值,例如:1234(来自 >1234)和 1000(来自 <1000)但不会存储 31(来自 31sadj),因为它没有任何符号
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-]+)')
我希望我的输出如下所示
答案 0 :(得分:2)
你可以使用
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][^<>=]*)
匹配项,搜索除 <
、>
和 =
之外的零个或多个字符,然后是一个字母然后又是零个或多个字符,除了 <
、>
和 =
。
我得到的输出:
>>> 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
答案 1 :(得分: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*(?=$)
: 第二个选项匹配行尾的数字(.+)?
: 第三个捕获组匹配匹配零次或一次
.+
:匹配任意字符一次或多次。