【问题标题】:How to remove a character from some rows in a dataframe column?如何从数据框列的某些行中删除字符?
【发布时间】:2021-06-16 22:27:20
【问题描述】:

我有一个大的 DataFrame 需要清理,作为示例,请查看此数据框:

import pandas as pd

cars = {'Brand': ['Honda Civic','Toyota Corolla','Ford Focus','Audi A4','Suzuki'],
        'Price': ['22000.T','25000.T','27000','.TPX','.NKM1']
        }

df = pd.DataFrame(cars, columns = ['Brand', 'Price'])

print (df)

我想从单词的末尾删除'.T',并且只从包含的行的开头删除'.'

通过以下代码行,我可以删除'.T'

df['Price'].replace('.T', '', regex=True)

但它也从'.TPX' 中删除了'T'

对此的任何建议表示赞赏。

0    22000
1    25000
2    27000
3       PX
4    .NKM1
Name: Price, dtype: object

也用于在我添加此行时删除 '.'

f['Price'].replace('.', '', regex=True)

我得到了一个与我预期不同的数据框

0    
1    
2    
3    
4    
Name: Price, dtype: object

【问题讨论】:

    标签: python regex pandas dataframe data-cleaning


    【解决方案1】:

    另一种方法是使用 numpy.where 并使用 str.startswithstr.endswith 评估您的条件:

    import numpy as np
    
    p = df['Price'].str
    df['Price'] = np.where(p.startswith('.'),p.replace('.','',regex=True),
                             np.where(p.endswith('.T'),p.replace('.T','',regex=True),p))
    

    这将检查df['Price'] 是以. 开头还是以.T 结尾并替换它们。

                Brand  Price
    0     Honda Civic  22000
    1  Toyota Corolla  25000
    2      Ford Focus  27000
    3         Audi A4    TPX
    4          Suzuki   NKM1
    

    【讨论】:

      【解决方案2】:

      Series.str.replace

      df['Price'] = df['Price'].str.replace(r'^(?:\.)?(.*?)(?:\.T)?$', r'\g<1>')
      

      Series.str.extract

      df['Price'] = df['Price'].str.extract(r'^(?:\.)?(.*?)(?:\.T)?$', expand=False)
      

                  Brand  Price
      0     Honda Civic  22000
      1  Toyota Corolla  25000
      2      Ford Focus  27000
      3         Audi A4    TPX
      4          Suzuki   NKM1
      

      正则表达式详细信息:

      • ^ : 在行首断言位置
      • (?:\.) :匹配字符 . 的非捕获组
      • ? :匹配前一个非捕获组零次或一次
      • (.*?) :捕获匹配除行终止符之外的任何字符零次或多次但尽可能少的组 (lazy match)
      • (?:\.T) :匹配 .T 的非捕获组
      • ? :匹配前一个非捕获组零次或一次
      • $ : 在行尾断言位置

      Regex demo

      【讨论】:

      • @anky 因为它还会在开头和结尾删除不需要的字符..考虑假想词ABCDDTTT.T 所以使用.rstrip(.T) 会导致ABCDD 这意味着它也会删除额外的@最后是 987654341@,这可能是不受欢迎的......虽然如果这不是数据集中的问题,那么我们绝对可以使用 rstrip.
      【解决方案3】:

      您应该能够通过锚点和所谓的积极后视来实现您想要的。

      df['Price'].replace('(?&lt;=.)\.T$', '', regex=True)

      对于正则表达式,有一些特殊字符增加了功能。在这里,'$' 表示以结尾。因此,如果您只想影响以“.T”结尾的刺痛,则需要将其添加到末尾。后面的表达式部分是'(?

      我真的不知道如何解释它,除了它有点类似于 CSS 类的工作方式,这真的不是一个很好的例子。

      '?

      替换以'.'开头的单词很简单。就是对面的锚,

      df['Price'].replace('^\.', '', regex=True)

      https://regex101.com/ 是一个很棒的网站,可以帮助您构建正则表达式。它还将解释您的正则表达式的作用。

      【讨论】:

        【解决方案4】:

        你也可以使用numpy.select:

        In [178]: import numpy as np
        
        In [179]: conds = [df.Price.str.endswith('.T'), df.Price.str.startswith('.')]
        In [182]: choices = [df.Price.str.replace('.T', '', regex=True), df.Price.str.replace('.', '', regex=True)]
        
        In [189]: df.Price = np.select(conds, choices, default=df.Price)
        
        In [190]: df
        Out[190]: 
                    Brand  Price
        0     Honda Civic  22000
        1  Toyota Corolla  25000
        2      Ford Focus  27000
        3         Audi A4    TPX
        4          Suzuki   NKM1
        

        【讨论】:

          【解决方案5】:

          您可以匹配字符串开头的点,也可以匹配结尾的.T。然后在替换中使用一个空字符串。

          \A\.|\.T\Z
          

          例如

          import pandas as pd
          
          cars = {'Brand': ['Honda Civic','Toyota Corolla','Ford Focus','Audi A4','Suzuki'],
                  'Price': ['22000.T','25000.T','27000','.TPX','.NKM1']
                  }
          
          df = pd.DataFrame(cars, columns = ['Brand', 'Price'])
          df['Price'] = df['Price'].replace(r"\A\.|\.T\Z", "", regex=True)
          print(df)
          

          输出

                      Brand  Price
          0     Honda Civic  22000
          1  Toyota Corolla  25000
          2      Ford Focus  27000
          3         Audi A4    TPX
          4          Suzuki   NKM1
          

          【讨论】:

            【解决方案6】:

            我想解释一下为什么你会得到这个结果。这是因为.在模式中使用时具有特殊含义,re docs特殊字符列表以

            开头

            .(点)在默认模式下,它匹配除 a 之外的任何字符 新队。如果已指定 DOTALL 标志,则匹配任何 包括换行符的字符。

            所以当你的意思是 literal . 你需要转义它,考虑下面的例子

            df = pd.DataFrame({"col1":["3.45"]})
            df["unescaped"] = df.col1.replace(r'.','X',regex=True)
            df["escaped"] = df.col1.replace(r'\.','X',regex=True)
            print(df)
            

            输出

               col1 unescaped escaped
            0  3.45      XXXX    3X45
            

            请注意,我在这里使用了所谓的原始字符串,它允许在模式中以更易读的形式转义具有特殊含义的字符(如果没有原始字符串,我将不得不写 '\\.',请参阅 re 文档以获取更多信息) .如果您对正则表达式模式感到困惑,我建议您使用regex101.com 来获得它的解释。

            【讨论】:

              【解决方案7】:

              使用

              >>> df['Price'].str.replace(r'^\.|\.T$', '', regex=True)
              0    22000
              1    25000
              2    27000
              3      TPX
              4     NKM1
              

              regex proof

              解释

              --------------------------------------------------------------------------------
                ^                        the beginning of the string
              --------------------------------------------------------------------------------
                \.                       '.'
              --------------------------------------------------------------------------------
               |                        OR
              --------------------------------------------------------------------------------
                \.                       '.'
              --------------------------------------------------------------------------------
                T                        'T'
              --------------------------------------------------------------------------------
                $                        before an optional \n, and the end of the
                                         string
              

              【讨论】:

                猜你喜欢
                • 2022-08-05
                • 1970-01-01
                • 1970-01-01
                • 2019-01-17
                • 1970-01-01
                • 2020-10-07
                • 1970-01-01
                • 1970-01-01
                • 2016-10-05
                相关资源
                最近更新 更多