在pandas数据框上应用正则表达式函数

5

我在pandas中有一个数据框,如下:

0                       1                   2
([0.8898668778942382    0.89533945283595]   0)
([1.2632564814188714    1.0207660696232244] 0)
([1.006649166957976     1.1180973832359227] 0)
([0.9653632916751714    0.8625538463644129] 0)
([1.038366333873932     0.9091449796555554] 0)

所有的值都是字符串。我想删除所有特殊字符并转换为双精度浮点数。我想应用一个函数,除了点号之外删除所有特殊字符。
import re
re.sub('[^0-9.]+', '',x)

所以我希望将其应用于数据帧的所有单元格。我该怎么做?我发现了df.applymap函数,但我不知道如何将字符串作为参数传递。我尝试了

def remSp(x): 
    re.sub('^[0-9]+', '',x)

df.applymap(remSp())

但是我不知道如何将单元格传递给函数。有更好的方法吗?

谢谢。


传递 remSp 时不要带上 (),参数是函数本身,而不是调用的结果。 - GPhilo
applymap函数将在数据框中的每个项目上调用'remSp'。 - GPhilo
你正在寻找 df.applymap(remSp),请注意,在传递函数之前,你不需要调用它,.applymap 将函数作为参数。请注意,你可能需要在正则表达式模式中添加一个 . 到你的组中... - juanpa.arrivillaga
我尝试了这个 [ df.applymap(remSp) ],但返回的数据框中所有值都是 None。 - Michail N
@MichailN 是的,因为你定义的 remSp 总是返回 None... - juanpa.arrivillaga
更好的答案在这里:https://dev59.com/PKXja4cB1Zd3GeqPKgKh#46114275... 一行代码解决问题... 欢迎采纳。 - cs95
3个回答

6
为什么不能直接使用默认的replace方法来处理带有正则表达式的df。即:
df = df.replace('[^\d.]', '',regex=True).astype(float)
          0         1    2
0  0.889867  0.895339  0.0
1  1.263256  1.020766  0.0
2  1.006649  1.118097  0.0
3  0.965363  0.862554  0.0
4  1.038366  0.909145  0.0
这是一个带有数据的表格,其中第一列到第二列的数字代表了具体数值。此外,这段代码比其他答案执行速度更快。

1
是的,这样更好...做得好。 - cs95
我尝试了这行代码,但是它给出了以下错误:"无法将字符串转换为浮点数"。有什么想法吗? - Mojgan Mazouchi
尝试移除 .astype(float) 并使用 .apply(lambda x: pd.to_numeric(x, errors='coerce'), 1),错误可能是由于某些列中存在 nan 或未知字符串所致。 - Bharath M Shetty

3
使用applymap
In [814]: df.applymap(lambda x: re.sub(r'[^\d.]+', '', x)).astype(float)
Out[814]:
          0         1    2
0  0.889867  0.895339  0.0
1  1.263256  1.020766  0.0
2  1.006649  1.118097  0.0
3  0.965363  0.862554  0.0
4  1.038366  0.909145  0.0

使用transform
In [809]: df.transform(lambda x: x.str.replace(r'[^\d.]+', '')).astype(float)
Out[809]:
          0         1    2
0  0.889867  0.895339  0.0
1  1.263256  1.020766  0.0
2  1.006649  1.118097  0.0
3  0.965363  0.862554  0.0
4  1.038366  0.909145  0.0

@COLDSPEED,尽管我喜欢一行代码的答案,但您的回答表现得更好,干得漂亮! - Michail N
@MichailN 添加了基准测试。说真的...单行代码已经被高估了。 - cs95
1
@COLDSPEED 有时候风格比性能更重要,但无论如何你是正确的。 - Michail N
@COLDSPEED 我不喜欢循环!一行代码统治天下! - Michail N
1
@cᴏʟᴅsᴘᴇᴇᴅ -- 我同意,我也很在意性能 ;) - Zero
显示剩余3条评论

2

遍历列,调用str.replace函数。

for c in df.columns:
    df[c] = df[c].str.replace('[^\d.]', '')

df = df.astype(float)
df
          0         1  2
0  0.889867  0.895339  0
1  1.263256  1.020766  0
2  1.006649  1.118097  0
3  0.965363  0.862554  0
4  1.038366  0.909145  0

很遗憾,pandas目前还不支持在整个数据框上进行字符串访问操作,因此除了循环列之外的替代方法将会更慢,例如使用lambda的applymap/transform


性能

小型

100 loops, best of 3: 2.04 ms per loop  # applymap 
100 loops, best of 3: 2.69 ms per loop  # transform
1000 loops, best of 3: 1.45 ms per loop  # looped str.replace

大型(df * 10000

1 loop, best of 3: 618 ms per loop  # applymap 
1 loop, best of 3: 658 ms per loop  # transform
1 loop, best of 3: 341 ms per loop  # looped str.replace
1 loop, best of 3: 212 ms per loop  # df.replace

在对原地操作和返回副本的函数进行基准测试时,您可能需要小心。在前一种情况下,在完成第一次替换后,剩余的99个测试循环实际上并没有执行相同的操作,明白吗? - Zero
@JohnGalt 让我重新运行一次,只用一个循环。 - cs95
另外,检查将 astype(float) 移动到循环内部是否可以进一步改善它。 - Zero
@JohnGalt 用单个循环重新运行。此外,将astype放入循环中会使情况变得更糟。 - cs95
@cᴏʟᴅsᴘᴇᴇᴅ 我的回答怎么样? - Bharath M Shetty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接