在Python中选择性地删除字符串之后的空格

时间:2017-07-17 11:59:32

标签: python pandas dataframe

我有以下代码片段:

    import pandas as pd

    df = pd.DataFrame([{'LastName':'VAN HOUTEN'},
                       {'LastName':"O'BOYLE"},
                       {'LastName':'ESTEVAN-GONZALEZ'},
                       {'LastName':'RODRIGO TEIXEIRA'},
                       {'LastName':'ESTEBAN GONZALEZ'}, 
                       {'LastName':'O ROURKE'},
                       {'LastName':'RODRIGO-TEIXEIRA'}])

    delete_space_after_list = ['VAN','O']

    df['NewName'] = df['LastName'].str.replace("'"," ")

    for s in delete_space_after_list[:]:
        df['NewName'] = df['NewName'].str.replace(s + ' ', s)

    df['NewName'] = df['NewName'].str.replace('-'," ")
    df['NewName'] = df['NewName'].str.split().str.get(0)   

运行此代码会给我以下结果:

    Index        LastName               NewName
    0            VAN HOUTEN             VANHOUTEN
    1            O'BOYLE                OBOYLE
    2            ESTEVAN-GONZALEZ       ESTEVAN
    3            RODRIGO TEIXEIRA       RODRIGOTEIXEIRA
    4            ESTEVAN GONZALEZ       ESTEVANGONZALEZ
    5            O ROURKE               OROURKE
    6            RODRIGO-TEIXEIRA       RODRIGO

然而,所需的输出是

    Index        LastName               DesiredName
    0            VAN HOUTEN             VANHOUTEN
    1            O'BOYLE                OBOYLE
    2            ESTEVAN-GONZALEZ       ESTEVAN
    3            RODRIGO TEIXEIRA       RODRIGO
    4            ESTEVAN GONZALEZ       ESTEVAN
    5            O ROURKE               OROURKE
    6            RODRIGO-TEIXEIRA       RODRIGO

它消除了RODRIGO之后的空间(因为LastName末尾的'O')并将其与'TEIXEIRA'连接,同样消除了ESTEVAN之后的空格(因为'{末尾的'VAN') 1}})并将其与'GONZALEZ'连接起来。但是,它正确地消除了其他名称中的空间。

如何让这段代码正确删除空格,就像它对VAN HOUTEN,O'BOYLE,ESTEVAN-GONZALEZ,O ROURKE和& RODRIGO-TEIXEIRA在ESTEVAN GONZALEZ&之后没有删除空白区域。 RODRIGO TEIXEIRA?

2 个答案:

答案 0 :(得分:2)

所以你想删除不那么重要的" name,由名称以OVAN结尾但 OVAN的名称后面的名称定义,并删除其他名字的非字母。

这是正则表达式的工作(或没有它们的漫长而痛苦的工作)

我会通过链接这样的2个正则表达式来做到这一点(因为问题与pandas没有直接关系,所以我放弃了pandas):

data = [{'LastName':'VAN HOUTEN'},
                       {'LastName':"O'BOYLE"},
                       {'LastName':'ESTEVAN-GONZALEZ'},
                       {'LastName':'RODRIGO TEIXEIRA'},
                       {'LastName':'ESTEVAN GONZALEZ'}, # not ESTEBAN as in your example!
                       {'LastName':'O ROURKE'},
                       {'LastName':'RODRIGO-TEIXEIRA'}]

import re

new_data = [re.sub("\W","",re.sub("(.)(O|VAN)\W.*",r"\1\2",v['LastName'])) for v in data]

print(new_data)

结果:

['VANHOUTEN', 'OBOYLE', 'ESTEVAN', 'RODRIGO', 'ESTEVAN', 'OROURKE', 'RODRIGO']

这样:

  • "(.)(O|VAN)\W.*"匹配至少一个字符,后跟OVAN前缀,后跟非字母(\W),其余的,我们跳过(我们只保留了2个第一组):处理不太重要的名称"
  • "\W"删除空格,短划线,引号...所有非字母数字。比处理第二种情况。

答案 1 :(得分:1)

大熊猫解决方案,正则表达不像让 - 弗朗索瓦法布尔那样干净,但它有效。

In [541]: import operator

In [542]:  df['LastName'].transform(lambda x: x.replace("[-']", ' ', regex=True) \
     ...:                                     .replace(r'^((?:O)|(?:VAN)) ', r'\1', regex=True) \
     ...:                                     .str.split()) \
     ...:                .map(operator.itemgetter(0))
     ...: 
Out[546]: 
0    VANHOUTEN
1       OBOYLE
2      ESTEVAN
3      RODRIGO
4      ESTEBAN
5      OROURKE
6      RODRIGO
Name: LastName, dtype: object
  1. replace("[-']", ' ', regex=True)将所有连字符和冒号转换为空格。

  2. replace(r'^((?:O)|(?:VAN)) ', r'\1', regex=True)在开始'O''VAN'后删除空格。

  3. str.split()分裂空间