Python 在Pandas中解析csv文件时,如何从字符串中删除额外的空白?

Python 在Pandas中解析csv文件时,如何从字符串中删除额外的空白?,python,parsing,pandas,Python,Parsing,Pandas,我有一个名为“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,Mer

我有一个名为“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数据框,以便该数据框如下所示:

       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
\s -> white-space
* -> any number (zero or many)
, -> no meaning, direct character match
我所能做的就是:

    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

如果没有这些空白,我如何获取数据帧?

嗯,空白在数据中,因此如果不读取空白,就无法读取数据。但是,读入后,您可以通过执行以下操作去除空白,例如,
df[“Make”]=df[“Make”].map(str.strip)
(其中
df
是您的数据帧)。

您可以使用转换器:

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

我没有足够的声誉留下评论,但是上面的答案建议使用
map
函数和
strip
如果您有NaN值,将不起作用,因为strip只对char有效,而NaN是float

有一个内置的pandas函数来实现这一点,我使用了:
pd.core.strings.str_strip(df['Description'])


其中,
df
是您的数据帧。在我的例子中,我在大约120万行的数据帧上使用了它,速度非常快。

添加参数
skipinitialspace=True

因此,请尝试:

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

pd.read\u csv()
中也可以使用同样的方法。这里有一个函数,用于迭代每列并应用
pd.core.strings.str\u 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
str.strip()函数在Series上运行得非常好。因此,我将包含空格的dataframe列转换为一个系列,使用str.strip()函数去除空格,然后将转换后的列替换回dataframe。下面是示例代码

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

我不相信Pandas在发布此问题时支持这一点,但最直接的方法是在
read\u csv
sep
参数中使用regex。因此,类似于以下内容的内容应该适用于此问题

table = pd.read_table("data.csv", sep=' *, *')
已弃用,以下是文档中显示的消息

自版本0.24.0以来已弃用

如有必要,请改用传递sep='\t'

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

sep="\s*,\s*"
任意数量的空格,后跟分隔符,再后跟任意数量的空格,这将确保所有前导空格和尾随空格也被选为分隔符块,从而删除数据两侧的空白

regex详情如下:

       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
\s -> white-space
* -> any number (zero or many)
, -> no meaning, direct character match
因此,正则表达式
\s*,\s*
代表
空格[任何数字]匹配逗号和空格[任何数字]


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

这对我很有帮助。我在数据中有像“NaN”这样的值,这使得它能够检测到NaN,而不管“NaN”前面有多大的空白,也不需要手动设置“na_值”参数。虽然转换器可以做到这一点,但对于大多数用例,
skipinitialspace=True
是人们想要的。应该是最好的答案!更简单的是
data['values']=data['values'].str.strip()
非常有用,尤其是当输出到不需要头或索引的txt文件时。这是唯一有效的解决方案
df[“Make”]=df[“Make”].map(str.strip)
然后我将
df.to_csv('no_head.txt',header=None,index=False)
这消除了空白。再次感谢这项工作很好,但在jupyter中还需要参数
engine=“python”
,或者它会转储混乱的警告解析警告:返回到“python”引擎,因为“c”引擎不支持正则表达式分隔符(分隔符>1个字符,与“\s+”不同的分隔符被解释为正则表达式);这个答案很老套。“没有足够的声誉”。目前有595和一个金色徽章如果您在CSV文件中引用了包含分隔符的字符串,此方法将不起作用,因为它会忽略引号。例如,像这样的行:
1,10.2,“foo,bar”,abc
将中断,因为
foo
bar
之间的逗号被解释为分隔符。我得到了以下错误:
parserror:saw32,第14行应该有31个字段。错误可能是由于在使用多字符分隔符时忽略了引号。
@Gabriel只需执行
read\u csv
,而不使用
sep
将文件读入pandas数据帧?是的,它将读取文件,但不会去除空白(这是OP的重点)。这里发布的其他解决方案之一将需要做到这一点。@Gabriel它仍然可以用正则表达式完成,但要用更复杂的表达式。我知道,尽管我对正则表达式不够精通,无法构造它!但问题是,我的csv文件的复杂正则表达式可能无法用于其他输入。这就是为什么我不认为这个解决方案像那些在加载步骤后去掉空白的解决方案那样优雅。处理数据帧的函数非常方便。记住返回对象,
df=df\u strip(df)