如何在 pandas 数据框的特定列中删除所有非数字字符?

52

我有一个类似这样的数据框:

     A       B           C
1   red78   square    big235
2   green   circle    small123
3   blue45  triangle  big657

我需要能够删除列 C 中所有行的非数字字符,以便我的数据框看起来像:

     A       B           C
1   red78   square    235
2   green   circle    123
3   blue45  triangle  657

我尝试使用以下内容但出现了错误,错误信息为“预期字符串或缓冲区”:

import re
dfOutput.imgID = dfOutput.imgID.apply(re.sub('[^0-9]','', dfOutput.imgID), axis = 0)

我应该做些什么呢?

创建数据框的代码:

dfObject = pd.DataFrame()
dfObject.set_value(1, 'A', 'red78')
dfObject.set_value(1, 'B', 'square')
dfObject.set_value(1, 'C', 'big235')
dfObject.set_value(2, 'A', 'green')
dfObject.set_value(2, 'B', 'circle')
dfObject.set_value(2, 'C', 'small123')
dfObject.set_value(3, 'A', 'blue45')
dfObject.set_value(3, 'B', 'triangle')
dfObject.set_value(3, 'C', 'big657')
6个回答

52

使用str.extract函数并传递一个正则表达式模式来提取仅包含数字的部分:

In[40]:
dfObject['C'] = dfObject['C'].str.extract('(\d+)', expand=False)
dfObject

Out[40]: 
        A         B    C
1   red78    square  235
2   green    circle  123
3  blue45  triangle  657

如果需要的话,您可以将其转换为int类型:

dfObject['C'] = dfObject['C'].astype(int)

17
如果使用 extract 这个函数,它只会从输入字段中提取一个数字序列。如果有多个由非数字字符分隔的数字部分,此答案只会提取第一个字符序列。 - meta4
这在Python 3.6.6中给了我`E:\WPy-3662\python-3.6.6.amd64\lib\site-packages\ipykernel_launcher.py:1: SettingWithCopyWarning: 尝试在DataFrame的切片副本上设置值。 请尝试使用.loc[row_indexer,col_indexer] = value代替请参阅文档:http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy """入口点启动IPython内核。` - Superdooperhero
1
@Superdooperhero,这意味着你的df是原始df的视图或切片,因此会出现警告。如果没有看到你的完整代码以及你是如何引起这个问题的,我无法发表评论。基本上,如果你想对副本进行操作,那么你可以使用df1 = df.copy(),然后你对df1所做的任何操作都不会产生警告。但是,如果你真的想在原始数据上进行操作,那么你需要使用.loc,这样就明确表示你要在视图上进行操作。相关信息请参见:https://dev59.com/8WIj5IYBdhLWcg3wHhlX - EdChum
谢谢。那个答案解决了问题。 - Superdooperhero
extract('(\d+)', expand=False) 似乎也会丢失浮点数的小数点。有没有什么方法可以防止这种情况发生? - Superdooperhero
2
@Superdooperhero,尝试使用正则表达式模式'(\d+\.*\d*)'或者直接使用其他答案将字符替换为空字符串,剩下的就是数字字符了。 - EdChum

28
要从Pandas列中的字符串中删除所有非数字字符,您应该使用 str.replace\D+[^0-9]+模式:
dfObject['C'] = dfObject['C'].str.replace(r'\D+', '')

又或者,由于在Python 3中,\D默认完全支持Unicode,并且因此不匹配非ASCII数字(例如۱۲۳۴۵۶۷۸۹,请参见证明),您应该考虑

dfObject['C'] = dfObject['C'].str.replace(r'[^0-9]+', '')
所以,
import re
print ( re.sub( r'\D+', '', '1۱۲۳۴۵۶۷۸۹0') )         # => 1۱۲۳۴۵۶۷۸۹0
print ( re.sub( r'[^0-9]+', '', '1۱۲۳۴۵۶۷۸۹0') )     # => 10

3
阿拉伯数字/印度数字,不错的选择 ;) - Umar.H
到目前为止,这是我最喜欢的(+1)。 - Tiago Martins Peres
最全面的解决方案 (+1) - Narin Dhatwalia

18
您可以使用正则表达式和.str.replace方法:
dfObject['C'] = dfObject.C.str.replace(r"[a-zA-Z]",'')

输出:

        A         B    C
1   red78    square  235
2   green    circle  123
3  blue45  triangle  657

7
关闭。这个答案将移除所有的字母数字字符。要移除所有非数字字符,请使用\D字符类。 - meta4

11

你也可以使用 lambda 函数和 str.isdigit 来完成此操作:

import pandas as pd

df = pd.DataFrame({'Name': ['John5', 'Tom 8', 'Ron 722']})

df['Name'] = df['Name'].map(lambda x: ''.join([i for i in x if i.isdigit()]))

#   Name
# 0    5
# 1    8
# 2  722

3

经过两年的时间,为了帮助他人,我认为您的答案非常接近。我使用了您的逻辑并使其实现。基本上,您需要创建一个执行清理的函数,然后将其应用于列C

import pandas as pd
import re

df = pd.DataFrame({
     'A': ['red78', 'green', 'blue45'],
     'B': ['square', 'circle', 'triangle'],
    'C': ['big235', 'small123',  'big657']
})

def remove_chars(s):
    return re.sub('[^0-9]+', '', s) 

df['C'] = df['C'].apply(remove_chars)
df

以下是结果:

A   B   C
0   red78   square  235
1   green   circle  123
2   blue45  triangle    657

0
假设我们想要从一个表的所有列中删除所有字符。

import pandas as pd
 

df = pd.DataFrame({
     'A': ['red78', 'green', 'blue45'],
     'B': ['square', 'circle', 'triangle'],
    'C': ['big235', 'small123',  'big657']
})
 df[['A', 'C']] = df[['A', 'C']].replace(regex=[r'\D+'], value="") 

Output:
   A         B    C
0  78    square  235
1        circle
2  45  triangle  657 


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