Python/有效的方法从每个 Pandas 数据框单元格中删除空格,其中包含类似对象的字符串

Posted

技术标签:

【中文标题】Python/有效的方法从每个 Pandas 数据框单元格中删除空格,其中包含类似对象的字符串【英文标题】:Pythonic/efficient way to strip whitespace from every Pandas Data frame cell that has a stringlike object in it 【发布时间】:2016-02-20 17:04:24 【问题描述】:

我正在将 CSV 文件读入 DataFrame。我需要从所有类似字符串的单元格中去除空格,而在 Python 2.7 中保持其他单元格不变。

这是我正在做的事情:

def remove_whitespace( x ):
    if isinstance( x, basestring ):
        return x.strip()
    else:
        return x

my_data = my_data.applymap( remove_whitespace )

Pandas 有没有更好或更惯用的方法来做到这一点?

有没有更有效的方法(也许是按列做事)?

我已经尝试寻找一个明确的答案,但是关于这个主题的大多数问题似乎是如何从列名本身中去除空格,或者假设单元格都是字符串。

【问题讨论】:

如果你对一个不是基本字符串实例的元素执行 x.strip() 会发生什么?如果没有任何缺点,也许您可​​以删除检查并将其替换为 try 和 except 块。这可能会加快速度。 您在使用pandas.read_csv (pandas.pydata.org/pandas-docs/version/0.17.0/generated/…) 吗?你试过skipinitialspace=True吗? @WarrenWeckesser 我可能在单元格中我关心的数据前后都有空格,所以我认为skipinitialspace只能解决一半的问题。 @JeffMandell - 尝试在非字符串对象(或没有 strip 方法的对象,例如数字数据类型)上调用 .strip() 将引发异常。没错,处理异常可能比检查更快 - 取决于异常的数据和频率。 @deadcode 我担心可能是这种情况。 【参考方案1】:

您可以使用 pandas 的 Series.str.strip() 方法对每个类似字符串的列快速执行此操作:

>>> data = pd.DataFrame('values': ['   ABC   ', '   DEF', '  GHI  '])
>>> data
      values
0     ABC   
1        DEF
2      GHI  

>>> data['values'].str.strip()
0    ABC
1    DEF
2    GHI
Name: values, dtype: object

【讨论】:

【参考方案2】:

当您调用pandas.read_csv 时,您可以使用匹配零个或多个空格的正则表达式,后跟一个逗号,后跟零个或多个空格作为分隔符。

例如,这里是"data.csv"

In [19]: !cat data.csv
1.5, aaa,  bbb ,  ddd     , 10 ,  XXX   
2.5, eee, fff  ,       ggg, 20 ,     YYY

(第一行以XXX后三个空格结束,第二行以最后一个Y结束。)

下面使用pandas.read_csv()读取文件,正则表达式' *, *'作为分隔符。 (使用正则表达式作为分隔符仅在read_csv()的“python”引擎中可用。)

In [20]: import pandas as pd

In [21]: df = pd.read_csv('data.csv', header=None, delimiter=' *, *', engine='python')

In [22]: df
Out[22]: 
     0    1    2    3   4    5
0  1.5  aaa  bbb  ddd  10  XXX
1  2.5  eee  fff  ggg  20  YYY

【讨论】:

这非常接近,但是引用的输入值有问题,例如:“a,b,c”,d 它不能从我想要的第一个字段中拉出空格存储在数据框的单元格中为 'a, b, c'【参考方案3】:

上面的“data['values'].str.strip()”答案对我不起作用,但我找到了一个简单的解决方法。我确信有更好的方法来做到这一点。 str.strip() 函数适用于 Series。因此,我将数据框列转换为系列,去除空格,将转换后的列替换回数据框。下面是示例代码。

import pandas as pd
data = pd.DataFrame('values': ['   ABC   ', '   DEF', '  GHI  '])
print ('-----')
print (data)

data['values'].str.strip()
print ('-----')
print (data)

new = pd.Series([])
new = data['values'].str.strip()
data['values'] = new
print ('-----')
print (new)

【讨论】:

【参考方案4】:

这是一个适用于 pandas 的按列解决方案:

import numpy as np

def strip_obj(col):
    if col.dtypes == object:
        return (col.astype(str)
                   .str.strip()
                   .replace('nan': np.nan))
    return col

df = df.apply(strip_obj, axis=0)

这会将对象类型列中的值转换为字符串。应谨慎使用混合类型的列。例如,如果您的列是带有 20001 和“21110”的邮政编码,那么您最终会得到“20001”和“21110”。

【讨论】:

【参考方案5】:

在寻找我可以使用的快速且简约的 sn-p 时偶然发现了这个问题。不得不自己从上面的帖子中组装一个。也许有人会觉得它有用:

data_frame_trimmed = data_frame.apply(lambda x: x.str.strip() if x.dtype == "object" else x)

【讨论】:

这完成了工作。如果您的标题也有尾随空格,请从***.com/a/21607530/4355695添加.rename(columns=lambda x: x.strip()) 如果 Pandas 将列标记为 object,此方法对我来说失败。 Pandas 会将混合数据类型的列标记为object,这并不一定意味着该列中的每个元素都是str Michael,对于真正的混合类型,你可以使用OP方法。 也许 isinstance(x, str) 将是一个更好的解决方案来检查它是否是一个字符串...... @MichaelSilverstein 在许多情况下,您可以首先使用 errors='ignore' 参数将所有列转换为数字(这会忽略任何具有在将其转换为数字时会导致错误的值的列):@987654328 @。然后你可以更安全地使用这个 sn-p 来去除空格。【参考方案6】:

我发现以下代码很有用,并且可能对其他人有所帮助。这个 sn-p 将允许您删除列中以及整个 DataFrame 中的空格,具体取决于您的用例。

import pandas as pd

def remove_whitespace(x):
    try:
        # remove spaces inside and outside of string
        x = "".join(x.split())

    except:
        pass
    return x

# Apply remove_whitespace to column only
df.orderId = df.orderId.apply(remove_whitespace)
print(df)


# Apply to remove_whitespace to entire Dataframe
df = df.applymap(remove_whitespace)
print(df)

【讨论】:

【参考方案7】:

我们希望:

    将我们的函数应用于数据框中的每个元素 - 使用 applymap

    使用type(x)==str(相对于x.dtype == 'object'),因为对于混合数据类型的列,Pandas 会将列标记为objectobject 列可能包含int 和/或str)。

    维护每个元素的数据类型(我们不想将所有内容都转换为str,然后去掉空格)。

因此,我发现以下是最简单的:

df.applymap(lambda x: x.strip() if type(x)==str else x)

【讨论】:

检查数据类型的另一种语法:isinstance(x, str) 而不是 type(x)==str 这似乎提供了足够的精确度,而不会过于激进和潜在的破坏性。【参考方案8】:

这对我有用 - 将其应用于整个数据框:

def panda_strip(x):
    r =[]
    for y in x:
        if isinstance(y, str):
            y = y.strip()

        r.append(y)
    return pd.Series(r)

df = df.apply(lambda x: panda_strip(x))

【讨论】:

df.apply(panda_strip) 更简洁。

以上是关于Python/有效的方法从每个 Pandas 数据框单元格中删除空格,其中包含类似对象的字符串的主要内容,如果未能解决你的问题,请参考以下文章

python将多个excel中的所有工作表附加到pandas数据框中的有效方法

Python Pandas 和 SciPy:识别点和计算移动向量的最佳方法

Python/Pandas/BigQuery:如何使用大量新的时间序列数据有效地更新现有表?

连接大型 CSV 文件中单词的最有效方法:pandas 还是 Python 标准库? [复制]

从大型元组/行列表中有效地构建 Pandas DataFrame

从大型元组/行列表中有效地构建 Pandas DataFrame