【问题标题】:Strip / trim all strings of a dataframe剥离/修剪数据框的所有字符串
【发布时间】:2017-04-18 10:23:09
【问题描述】:

在 python/pandas 中清理多类型数据框的值,我想修剪字符串。我目前正在按照两个说明进行操作:

import pandas as pd

df = pd.DataFrame([['  a  ', 10], ['  c  ', 5]])

df.replace('^\s+', '', regex=True, inplace=True) #front
df.replace('\s+$', '', regex=True, inplace=True) #end

df.values

这很慢,我有什么可以改进的?

【问题讨论】:

  • df.replace(r'\s*(.*?)\s*', r'\1', regex=True)
  • 这是最好的答案,刚刚登录以对@MaxU 的答案进行投票

标签: python regex pandas dataframe trim


【解决方案1】:

你可以使用Series对象的apply function

>>> df = pd.DataFrame([['  a  ', 10], ['  c  ', 5]])
>>> df[0][0]
'  a  '
>>> df[0] = df[0].apply(lambda x: x.strip())
>>> df[0][0]
'a'

注意strip 的用法,而不是更快的regex

另一个选项 - 使用 DataFrame 对象的apply function

>>> df = pd.DataFrame([['  a  ', 10], ['  c  ', 5]])
>>> df.apply(lambda x: x.apply(lambda y: y.strip() if type(y) == type('') else y), axis=0)

   0   1
0  a  10
1  c   5

【讨论】:

  • df[0] = df[0].str.strip() - 在更大的 DF 上很可能会更快
【解决方案2】:

您可以使用DataFrame.select_dtypes 选择string 列,然后使用apply 函数str.strip

注意:值不能像 dictslists 那样为 types,因为它们的 dtypesobject

df_obj = df.select_dtypes(['object'])
print (df_obj)
0    a  
1    c  

df[df_obj.columns] = df_obj.apply(lambda x: x.str.strip())
print (df)

   0   1
0  a  10
1  c   5

但如果只有几列,请使用str.strip

df[0] = df[0].str.strip()

【讨论】:

【解决方案3】:

如果你真的想使用正则表达式,那么

>>> df.replace('(^\s+|\s+$)', '', regex=True, inplace=True)
>>> df
   0   1
0  a  10
1  c   5

但是这样做应该更快:

>>> df[0] = df[0].str.strip()

【讨论】:

    【解决方案4】:

    你可以试试:

    df[0] = df[0].str.strip()
    

    或更具体地,适用于所有字符串列

    non_numeric_columns = list(set(df.columns)-set(df._get_numeric_data().columns))
    df[non_numeric_columns] = df[non_numeric_columns].apply(lambda x : str(x).strip())
    

    【讨论】:

      【解决方案5】:

      金钱射击

      这是一个使用applymap 的简洁版本,它带有一个简单的 lambda 表达式,仅当值是字符串类型时才调用strip

      df.applymap(lambda x: x.strip() if isinstance(x, str) else x)
      

      完整示例

      一个更完整的例子:

      import pandas as pd
      
      
      def trim_all_columns(df):
          """
          Trim whitespace from ends of each value across all series in dataframe
          """
          trim_strings = lambda x: x.strip() if isinstance(x, str) else x
          return df.applymap(trim_strings)
      
      
      # simple example of trimming whitespace from data elements
      df = pd.DataFrame([['  a  ', 10], ['  c  ', 5]])
      df = trim_all_columns(df)
      print(df)
      
      
      >>>
         0   1
      0  a  10
      1  c   5
      

      工作示例

      这是一个由 trinket 托管的工作示例: https://trinket.io/python3/e6ab7fb4ab

      【讨论】:

      • 嗨@DaleKube ...我刚刚在一台新机器上尝试了这个新机器,就像一个健全性检查一样,我得到了与答案中发布的相同的结果。您能否确认您使用的是 Python2 还是 Python3?这些天我只使用 Python3,但也许这可能是一个因素。如果是这样,如果您能够确认,我会在我发布的答案中注明。谢谢!
      • 我删除了我的评论。我在我的代码中发现了一个错误,我可以确认它现在就像一个魅力。仅供参考,我正在使用 Python 3。很抱歉给您带来麻烦。
      • 你应该使用type(x) == str,而不是type(x) is str
      • @fjsj 感谢您的推动。我已经使用支持isinstance(x, str) 的 PEP8 指南更新了示例。
      【解决方案6】:
      def trim(x):
          if x.dtype == object:
              x = x.str.split(' ').str[0]
          return(x)
      
      df = df.apply(trim)
      

      【讨论】:

      • 你能解释一下这个函数在做什么吗?
      • 比如我在日常工作中遇到这样的数据:가나다 봻左边空白是我想要的,右边是垃圾。 trim 函数从原始数据中提取我想要的。
      • 投反对票,因为这不会修剪字符串,它会删除第一个空格之后的所有内容。这不是问题中要求的行为,并引入了读者可能没有预料到的副作用。此外,副作用可能不会立即显现。如果您尝试修剪一列姓氏,您可能会认为这是按预期工作的,因为大多数人没有多个姓氏,并且尾随空格被删除。然后一个有两个姓氏的葡萄牙人加入您的网站,代码会删除他们的姓氏,只留下他们的第一个姓氏。
      【解决方案7】:

      怎么样(对于字符串列)

      df[col] = df[col].str.replace(" ","")
      

      永不失败

      【讨论】:

        【解决方案8】:
        # First inspect the dtypes of the dataframe
        df.dtypes
        
        # Then strip white spaces
        df.apply(lambda x: x.str.strip() if isinstance(x, object) else x)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-11-01
          • 2016-05-11
          • 2020-10-29
          • 1970-01-01
          • 2017-11-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多