【问题标题】:How can I remove extra whitespace from strings when parsing a csv file in Pandas?在 Pandas 中解析 csv 文件时,如何从字符串中删除多余的空格?
【发布时间】:2012-11-03 08:44:54
【问题描述】:

我有以下名为“data.csv”的文件:

    1997,Ford,E350
    1997, Ford , E350
    1997,Ford,E350,"Super, luxurious truck"
    1997,Ford,E350,"Super ""luxurious"" truck"
    1997,Ford,E350," Super luxurious truck "
    "1997",Ford,E350
    1997,Ford,E350
    2000,Mercury,Cougar

我想将其解析为 pandas DataFrame,以便 DataFrame 如下所示:

       Year     Make   Model              Description
    0  1997     Ford    E350                     None
    1  1997     Ford    E350                     None
    2  1997     Ford    E350   Super, luxurious truck
    3  1997     Ford    E350  Super "luxurious" truck
    4  1997     Ford    E350    Super luxurious truck
    5  1997     Ford    E350                     None
    6  1997     Ford    E350                     None
    7  2000  Mercury  Cougar                     None

我能做的最好的就是:

    pd.read_table("data.csv", sep=r',', names=["Year", "Make", "Model", "Description"])

这让我很兴奋:

    Year     Make   Model              Description
 0  1997     Ford    E350                     None
 1  1997    Ford     E350                     None
 2  1997     Ford    E350   Super, luxurious truck
 3  1997     Ford    E350  Super "luxurious" truck
 4  1997     Ford    E350   Super luxurious truck 
 5  1997     Ford    E350                     None
 6  1997     Ford    E350                     None
 7  2000  Mercury  Cougar                     None

如何获得没有这些空格的 DataFrame?

【问题讨论】:

    标签: python parsing pandas


    【解决方案1】:

    你可以使用转换器:

    import pandas as pd
    
    def strip(text):
        try:
            return text.strip()
        except AttributeError:
            return text
    
    def make_int(text):
        return int(text.strip('" '))
    
    table = pd.read_table("data.csv", sep=r',',
                          names=["Year", "Make", "Model", "Description"],
                          converters = {'Description' : strip,
                                        'Model' : strip,
                                        'Make' : strip,
                                        'Year' : make_int})
    print(table)
    

    产量

       Year     Make   Model              Description
    0  1997     Ford    E350                     None
    1  1997     Ford    E350                     None
    2  1997     Ford    E350   Super, luxurious truck
    3  1997     Ford    E350  Super "luxurious" truck
    4  1997     Ford    E350    Super luxurious truck
    5  1997     Ford    E350                     None
    6  1997     Ford    E350                     None
    7  2000  Mercury  Cougar                     None
    

    【讨论】:

      【解决方案2】:

      将参数 skipinitialspace=True 添加到 read_table 对我有用。

      那就试试吧:

      pd.read_table("data.csv", 
                    sep=r',', 
                    names=["Year", "Make", "Model", "Description"], 
                    skipinitialspace=True)
      

      pd.read_csv() 也有同样的效果。

      【讨论】:

      • 这对我有帮助。我在数据中有像“NaN”这样的值,这使得它可以检测到 NaN,无论“NaN”前面有多少空格并且无需手动设置“na_values”参数。
      • 虽然转换器可以做到这一点以及更多,但对于大多数用例来说,skipinitialspace=True 是人们想要的。应该是最佳答案!
      【解决方案3】:

      好吧,空白在您的数据中,因此如果不读取空白,您将无法读取数据。但是,在您读入之后,您可以通过执行例如 df["Make"] = df["Make"].map(str.strip)(其中 df 是您的数据框)来去除空格。

      【讨论】:

      • 超级有用,尤其是在输出到不需要标题或索引的 txt 文件时。这是唯一有效的解决方案。 df["Make"] = df["Make"].map(str.strip) 然后我申请了df.to_csv('no_head.txt',header=None,index=False),这消除了空格。再次感谢
      【解决方案4】:

      我没有足够的声誉来发表评论,但是如果您有 NaN 值,上面建议使用 map 函数和 strip 的答案将不起作用,因为 strip 仅适用于字符,而 NaN 是浮动。

      有一个内置的 pandas 函数可以做到这一点,我使用了它: pd.core.strings.str_strip(df['Description'])
      其中df 是您的数据框。在我的例子中,我在大约 120 万行的数据帧上使用了它,而且速度非常快。

      【讨论】:

      • 这个答案很好。 “没有足够的声誉”。目前有 595 和一个金徽章
      【解决方案5】:

      我不相信 Pandas 在发布此问题时支持这一点,但最直接的方法是在 read_csvsep 参数中使用正则表达式。因此,类似以下内容应该可以解决此问题。

      table = pd.read_table("data.csv", sep=' *, *')
      

      【讨论】:

      • 这很好用,但在 jupyter 中还需要参数 engine="python" 或者它会转储混乱的警告 ParserWarning: Falling backing to the 'python' engine because the 'c' engine does not support regex separators (separators > 1 个字符且不同于 '\s+' 被解释为正则表达式);
      【解决方案6】:

      read_table弃用,这是文档中显示的消息。

      自 0.24.0 版起已弃用。

      改用pandas.read_csv(),必要时传递sep='\t'。

      因此,使用 read_csv 您可以为 sep 参数传入一个正则表达式,您可以在其中将分隔符指定为

      sep="\s*,\s*"
      

      任意数量的空格,后跟分隔符,再后跟任意数量的空格,这将确保所有前导和尾随空格也被选为分隔符块,然后删除数据两侧的空格。

      正则表达式详情如下:

      \s -> white-space
      * -> any number (zero or many)
      , -> no meaning, direct character match
      

      所以,正则表达式\s*,\s* 代表white-space[any number] match a comma and white-space[any number]

      如果您的分隔符不是逗号,则将上述表达式中的, 替换为您的分隔符。例如:\s*;\s* 如果; 是您的分隔符。

      【讨论】:

      • 如果您在 CSV 文件中引用了包含分隔符的字符串,则此方法将不起作用,因为它会忽略引号。例如,像这样的行:1,10.2,"foo,bar",abc 将由于foobar 之间的逗号被解释为分隔符而中断。我收到以下错误:ParserError: Expected 31 fields in line 14, saw 32. Error could possibly be due to quotes being ignored when a multi-char delimiter is used.
      • @Gabriel 只是在没有sep 的情况下执行read_csv 将文件读入pandas dataFrame?
      • 是的,它会读取文件,但不会删除空格(这是 OP 的重点)。要做到这一点,需要使用此处发布的其他解决方案之一。
      • @Gabriel 它仍然可以使用正则表达式完成,但表达式要复杂得多。
      • 我知道,尽管我对正则表达式的熟练程度不足以构建它!但关键是我的 csv 文件的复杂正则表达式可能不适用于其他输入。这就是为什么我认为这个解决方案不如那些在加载步骤后去除空白的解决方案那么优雅。
      【解决方案7】:

      这是一个遍历每一列并应用pd.core.strings.str_strip的函数:

      def df_strip(df):
        df = df.copy()
        for c in df.columns:
          if df[c].dtype == np.object:
            df[c] = pd.core.strings.str_strip(df[c])
          df = df.rename(columns={c:c.strip()})
        return df
      

      【讨论】:

      • 处理数据帧的非常方便的函数。记得返回对象,df = df_strip(df)
      【解决方案8】:

      str.strip() 函数在 Series 上运行得非常好。因此,我将包含空格的数据框列转换为系列,使用 str.strip() 函数去除空格,然后将转换后的列替换回数据框。下面是示例代码。

      import pandas as pd
      data = pd.DataFrame({'values': ['   ABC   ', '   DEF', '  GHI  ']})
      new = pd.Series([])
      new = data['values'].str.strip()
      data['values'] = new
      

      【讨论】:

      • 更简单的是data['values'] = data['values'].str.strip()
      【解决方案9】:

      对我来说最好的方法是

      def read_csv_regex(data, date_columns=[]):
          df = pd.read_csv(data, quotechar='"', parse_dates=date_columns)
      
          # remove front and ending blank spaces
          df = df.replace({"^\s*|\s*$":""}, regex=True) 
      
          # if there remained only empty string "", change to Nan
          df = df.replace({"":np.nan}) 
          return df
      

      您不需要编写转换器函数并将其设置为每一列,它适用于头部和尾部空间,并且现在与 regexp sep 不同的是配额问题。

      https://towardsdatascience.com/dealing-with-extra-white-spaces-while-reading-csv-in-pandas-67b0c2b71e6a#9281

      【讨论】:

        猜你喜欢
        • 2011-08-05
        • 2013-06-03
        • 1970-01-01
        • 2022-10-07
        • 1970-01-01
        • 2022-07-24
        相关资源
        最近更新 更多