删除列中字符串中不需要的部分

2025-01-03 08:41:00
admin
原创
99
摘要:问题描述:我正在寻找一种有效的方法来从 DataFrame 列中的字符串中删除不需要的部分。数据如下: time result 1 09:00 +52A 2 10:00 +62B 3 11:00 +44a 4 12:00 +30b 5 13:00 ...

问题描述:

我正在寻找一种有效的方法来从 DataFrame 列中的字符串中删除不需要的部分。

数据如下:

    time    result
1    09:00   +52A
2    10:00   +62B
3    11:00   +44a
4    12:00   +30b
5    13:00   -110a

我需要将这些数据修剪为:

    time    result
1    09:00   52
2    10:00   62
3    11:00   44
4    12:00   30
5    13:00   110

我尝试.str.lstrip('+-')过 . str.rstrip('aAbBcC'),但出现错误:

TypeError: wrapper() takes exactly 1 argument (2 given)

任何指点都将不胜感激!


解决方案 1:

data['result'] = data['result'].map(lambda x: x.lstrip('+-').rstrip('aAbBcC'))

解决方案 2:

如何从列中的字符串中删除不需要的部分?

在最初的问题发布六年后,pandas 现在拥有大量“矢量化”字符串函数,可以简洁地执行这些字符串操作操作。

这个答案将探讨其中一些字符串函数,提出更快的替代方案,并在最后进行时间比较。


.str.replace

指定要匹配的子字符串/模式,以及要替换它的子字符串。

pd.__version__
# '0.24.1'

df    
    time result
1  09:00   +52A
2  10:00   +62B
3  11:00   +44a
4  12:00   +30b
5  13:00  -110a
df['result'] = df['result'].str.replace(r'D', '', regex=True)
df

    time result
1  09:00     52
2  10:00     62
3  11:00     44
4  12:00     30
5  13:00    110

如果需要将结果转换为整数,可以使用Series.astype

df['result'] = df['result'].str.replace(r'D', '', regex=True).astype(int)

df.dtypes
time      object
result     int64
dtype: object

如果您不想df就地修改,请使用DataFrame.assign

df2 = df.assign(result=df['result'].str.replace(r'D', '', regex=True))
df
# Unchanged

.str.extract

对于提取您想要保留的子字符串很有用。

df['result'] = df['result'].str.extract(r'(d+)', expand=False)
df

    time result
1  09:00     52
2  10:00     62
3  11:00     44
4  12:00     30
5  13:00    110

使用 时extract,需要指定至少一个捕获组。expand=False将返回一个包含来自第一个捕获组的捕获项的系列。


.str.split并且

拆分有效,假设所有字符串都遵循这种一致的结构。.str.get

# df['result'] = df['result'].str.split(r'D').str[1]
df['result'] = df['result'].str.split(r'D').str.get(1)
df

    time result
1  09:00     52
2  10:00     62
3  11:00     44
4  12:00     30
5  13:00    110

如果您正在寻找通用解决方案,则不推荐。


如果您对上述简洁易读的str
基于访问器的解决方案感到满意,那么您可以停在这里。但是,如果您对更快、更高效的替代方案感兴趣,请继续阅读。


优化:列表推导

在某些情况下,列表推导比 pandas 字符串函数更受青睐。原因是字符串函数本质上很难矢量化(真正意义上),因此大多数字符串和正则表达式函数只是循环的包装器,开销更大。

我的文章Pandas 中的 for 循环真的很糟糕吗?我应该何时关注它?对此进行了更详细的介绍。

str.replace选项可以使用以下方式重写re.sub

import re

# Pre-compile your regex pattern for more performance.
p = re.compile(r'D')
df['result'] = [p.sub('', x) for x in df['result']]
df

    time result
1  09:00     52
2  10:00     62
3  11:00     44
4  12:00     30
5  13:00    110

str.extract可以使用列表推导重写该示例re.search

p = re.compile(r'd+')
df['result'] = [p.search(x)[0] for x in df['result']]
df

    time result
1  09:00     52
2  10:00     62
3  11:00     44
4  12:00     30
5  13:00    110

如果可能出现 NaN 或不匹配,则需要重写上述代码以包含一些错误检查。我使用函数执行此操作。

def try_extract(pattern, string):
    try:
        m = pattern.search(string)
        return m.group(0)
    except (TypeError, ValueError, AttributeError):
        return np.nan
 
p = re.compile(r'd+')
df['result'] = [try_extract(p, x) for x in df['result']]
df

    time result
1  09:00     52
2  10:00     62
3  11:00     44
4  12:00     30
5  13:00    110

我们还可以使用列表推导重写@eumiro 和@MonkeyButter 的答案:

df['result'] = [x.lstrip('+-').rstrip('aAbBcC') for x in df['result']]

和,

df['result'] = [x[1:-1] for x in df['result']]

适用与处理 NaN 等相同的规则。


性能比较

在此处输入图片描述

使用perfplot生成的图表。完整代码列表,供您参考。相关函数如下所列。

其中一些比较是不公平的,因为它们利用了 OP 数据的结构,但你可以从中得到你想要的东西。需要注意的一点是,每个列表理解函数要么比其等效的 pandas 变体更快,要么具有可比性。

功能

def eumiro(df):
    return df.assign(
        result=df['result'].map(lambda x: x.lstrip('+-').rstrip('aAbBcC')))
    
def coder375(df):
    return df.assign(
        result=df['result'].replace(r'D', r'', regex=True))

def monkeybutter(df):
    return df.assign(result=df['result'].map(lambda x: x[1:-1]))

def wes(df):
    return df.assign(result=df['result'].str.lstrip('+-').str.rstrip('aAbBcC'))

def cs1(df):
    return df.assign(result=df['result'].str.replace(r'D', ''))

def cs2_ted(df):
    # `str.extract` based solution, similar to @Ted Petrou's. so timing together.
    return df.assign(result=df['result'].str.extract(r'(d+)', expand=False))

def cs1_listcomp(df):
    return df.assign(result=[p1.sub('', x) for x in df['result']])

def cs2_listcomp(df):
    return df.assign(result=[p2.search(x)[0] for x in df['result']])

def cs_eumiro_listcomp(df):
    return df.assign(
        result=[x.lstrip('+-').rstrip('aAbBcC') for x in df['result']])

def cs_mb_listcomp(df):
    return df.assign(result=[x[1:-1] for x in df['result']])

解决方案 3:

我会使用 pandas 替换函数,非常简单且功能强大,因为您可以使用正则表达式。下面我使用正则表达式 \D 来删除任何非数字字符,但显然您可以使用正则表达式发挥创造力。

data['result'].replace(regex=True,inplace=True,to_replace=r'D',value=r'')

解决方案 4:

在特定情况下,如果您知道要从数据框列中删除的位置数,则可以在 lambda 函数中使用字符串索引来删除这些部分:

最后一个字符:

data['result'] = data['result'].map(lambda x: str(x)[:-1])

前两个字符:

data['result'] = data['result'].map(lambda x: str(x)[2:])

解决方案 5:

这里有一个错误:目前无法将参数传递给str.lstripstr.rstrip

http://github.com/pydata/pandas/issues/2411

编辑:2012-12-07 这现在可以在 dev 分支上运行:

In [8]: df['result'].str.lstrip('+-').str.rstrip('aAbBcC')
Out[8]: 
1     52
2     62
3     44
4     30
5    110
Name: result

解决方案 6:

一种非常简单的方法是使用extract方法来选择所有数字。只需为其提供'd+'提取任意数字的正则表达式即可。

df['result'] = df.result.str.extract(r'(d+)', expand=True).astype(int)
df

    time  result
1  09:00      52
2  10:00      62
3  11:00      44
4  12:00      30
5  13:00     110

解决方案 7:

假设你的 DF 在数字之间也有这些额外的字符。最后一个条目。

  result   time
0   +52A  09:00
1   +62B  10:00
2   +44a  11:00
3   +30b  12:00
4  -110a  13:00
5   3+b0  14:00

您可以尝试 str.replace 不仅从开始和结束处删除字符,还可以从中间删除字符。

DF['result'] = DF['result'].str.replace('+|a|b|-|A|B', '')

输出:

  result   time
0     52  09:00
1     62  10:00
2     44  11:00
3     30  12:00
4    110  13:00
5     30  14:00

解决方案 8:

我经常使用列表推导来完成这些类型的任务,因为它们通常更快。

执行此类操作(即修改 DataFrame 中系列的每个元素)的各种方法之间的性能可能会有很大差异。通常,列表理解可能是最快的 - 请参阅下面有关此任务的代码竞赛:

import pandas as pd
#Map
data = pd.DataFrame({'time':['09:00','10:00','11:00','12:00','13:00'], 'result':['+52A','+62B','+44a','+30b','-110a']})
%timeit data['result'] = data['result'].map(lambda x: x.lstrip('+-').rstrip('aAbBcC'))
10000 loops, best of 3: 187 µs per loop
#List comprehension
data = pd.DataFrame({'time':['09:00','10:00','11:00','12:00','13:00'], 'result':['+52A','+62B','+44a','+30b','-110a']})
%timeit data['result'] = [x.lstrip('+-').rstrip('aAbBcC') for x in data['result']]
10000 loops, best of 3: 117 µs per loop
#.str
data = pd.DataFrame({'time':['09:00','10:00','11:00','12:00','13:00'], 'result':['+52A','+62B','+44a','+30b','-110a']})
%timeit data['result'] = data['result'].str.lstrip('+-').str.rstrip('aAbBcC')
1000 loops, best of 3: 336 µs per loop

解决方案 9:

尝试使用正则表达式:

import re
data['result'] = data['result'].map(lambda x: re.sub('[-+A-Za-z]',x)

解决方案 10:

当数据维度很大时,使用“str.replace”比 lambda 和 map 更快:

your_data["result"]=your_data["result"].str.replace("+","")
your_data["result"]=your_data["result"].str.replace("-","")

解决方案 11:

df['result']=df['result'].apply(lambda x:x.lstrip('-+').rstrip('abcABC'))
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用