仅从dataframe列的起始位置删除字符

2024-06-16 11:56:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我从两个输入Excel文件中获取数据,并在pandas dataframe的帮助下对其进行处理。Excel数据量大,列数多。然而,我创建了一些简单的例子来说明这个问题

以下是第一个数据帧df_s1(需要对零件号列执行操作)- first input dataframe

下面是第二个数据帧df_s2(这里提到了一些特殊字符,我只需从df_s1[‘零件号’]的开头删除这些字符,这些字符非常大,包括、2、(*2)等,我提到了有限)- Second datframe

在df_s2的帮助下处理df_s1之后,我需要以下输出- Output dataframe

现在的问题是,我必须删除(删除)df_s1(第一个数据帧)中零件号列开头的所有特殊字符。关于这些特殊字符的信息在df_s2(第二个数据帧特殊字符列(大量字符包括(,*…)

我已经尝试了以下代码来实现它。我还在代码中准备了示例数据帧,这样它将易于解决)

#first dataframe and remove special charaters from starting of part number column

import pandas as pd
df_s1 = pd.DataFrame({'Part Number' : ['(2)CAB-ETHS-RJ45',' 2*VEDGE-CAB-C13-XXX','(4X)CAB-ETHXOVER','1*VEDGE-ABCD','2*73ETHER-387','4xCBTA-98CD','5xNBOC','(1)289RG7','2 CDXG59','(7x)29FG2ZT-AB','((*2)FGDT-X78','((4))RGD-RX78','EDXC-Y82','D92ZT-3A','FTZT-9A7'], 
                    'ID' : ['1','2','3','4','4','4','4','4','4','4','4','5','4','4','6']
                  })
#Following special charaters needs to remove from starting of part number column of first dataframe
df_s2 = pd.DataFrame({'Special Charater':['(2)','2*','(4X)','1*','4x','5x','(1)','2 ','(7x)','((*2)','((4))']})
for i in df_s2['Special Charater']:
    j=0
    for k in df_s1['Part Number']:
        if str(k).startswith(str(i)):
            df_s1['Part Number'][j] = str(k[len(i):])

        
        else:
            j+=1

df_s1

然而,我从上面的代码中得到以下所需的输出,除了1个零件号2*VEDGE-CAB-C13-XXX,其中2*没有被删除

output of my code

我正在寻找-

  1. 我知道这不是通过pandas来完成这项任务的标准方法。所以你能帮助我使用你的pandas python解决方案吗。我无法在我的解决方案中使用这种类型的标准方法。我们必须替换所有提到的字符,因为它位于从第一个数据帧零件号列开始的第二个数据帧中
  2. 我无法理解为什么在我的解决方案中2*VEDGE-CAB-C13-XXX2*没有从起始位置删除,而其他特殊字符从起始位置删除

希望我清楚并且非常积极地找到解决这个问题的另一种方法


Tags: of数据代码numberdataframepandasdf字符
2条回答

1ts尝试

您可以使用pandas中的^{}。这将对字符串应用正则表达式,并为每个组返回一列。因为您想要完全匹配,所以只需要colmn0中的第一个组

df['Part Number'].str.extract('(([A-Z\d]+)+(-.*)?)$', expand=False)[0]

{}做什么

  • $是字符串的结尾,因此我们只希望在末尾有组
  • (-.*)?是一个组,它匹配-之后的所有字母。该组可以被找到零次或多次,用?表示
  • ([A-Z\d]+)是至少匹配一个大写字母或数字的组

这两个组的组合就是要推断的字符串

第二次尝试

您可以定义一个正则表达式并使用pandas^{}选项。 据我所见,您希望在asterix*、空空间x或右括号)之前重新封装所有元素。下面的代码尝试从字符串的左侧开始,最多查找1个匹配项

df_s1['Part Number'].str.replace('(.*[x| |\)|\*])', '', n=1)

第三次尝试

您可以尝试下面的代码,因为您知道要替换的所有字符串。在这种情况下,您将在每个字符串上循环多次,如果发现不需要的子字符串,则将该字符串替换为空字符串

def replace(x):
    for item in ['(2)','2*','(4X)','1*','4x','5x','(1)','2 ','(7x)','((*2)','((4))']:
        x = x.replace(item, '')
    return x

df_s1['Part Number'].apply(replace)

您可以尝试以下代码以获得替代解决方案:

import re

for sp_char in df_s2['Special Character']:
    df_s1['Part Number'] = df_s1['Part Number'].replace({'^'+re.escape(sp_char): ""}, regex=True)

print(df_s1)

re.escape()专门用于向所有特殊字符添加反斜杠(这可能是您尝试的某些解决方案不起作用的原因)


在进一步的工作中,我能够使用dictionary选项使代码更加优化。早期使用for循环的方法大约需要25-80ms,字典方法大约需要3-20ms。更新后的方法将占用更多内存,如果数据库相当大,则应记住更新后的方法

请注意,我还添加了^,这将使正则表达式只匹配字符串开头的字符

import re

replace_dict = {'^'+re.escape(sp_char): '' for sp_char in df_s2['Special Character']}
df_s1['Part Number'] = df_s1['Part Number'].replace(replace_dict, regex=True)

相关问题 更多 >