【问题标题】:Properly trimming whitespace across an entire pandas dataframe?正确修剪整个熊猫数据框中的空白?
【发布时间】:2020-07-14 12:42:49
【问题描述】:

我正在尝试完成一项简单的任务,即修剪数据框中每一列的所有空白。我有一些在单词之后、单词之前有尾随空格的值,以及一些只包含" " 值的列。我想把所有这些都去掉。

我阅读了this post,它提供了一个很好的方法来实现这一点: data_frame_trimmed = data_frame.apply(lambda x: x.str.strip() if x.dtype == "object" else x)

但是,我经常得到以下信息:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-9-31d35db1d48c> in <module>
      1 df = (pd.read_csv('C:\\Users\\wundermahn\Desktop\\aggregated_po_data.csv',
----> 2                     encoding = "ISO-8859-1", low_memory=False).apply(lambda x: x.str.strip() if (x.dtype == "object") else x))
      3 print(df.shape)
      4 
      5 label = df['class']

c:\python367-64\lib\site-packages\pandas\core\frame.py in apply(self, func, axis, raw, result_type, args, **kwds)
   6876             kwds=kwds,
   6877         )
-> 6878         return op.get_result()
   6879 
   6880     def applymap(self, func) -> "DataFrame":

c:\python367-64\lib\site-packages\pandas\core\apply.py in get_result(self)
    184             return self.apply_raw()
    185 
--> 186         return self.apply_standard()
    187 
    188     def apply_empty_result(self):

c:\python367-64\lib\site-packages\pandas\core\apply.py in apply_standard(self)
    294             try:
    295                 result = libreduction.compute_reduction(
--> 296                     values, self.f, axis=self.axis, dummy=dummy, labels=labels
    297                 )
    298             except ValueError as err:

pandas\_libs\reduction.pyx in pandas._libs.reduction.compute_reduction()

pandas\_libs\reduction.pyx in pandas._libs.reduction.Reducer.get_result()

<ipython-input-9-31d35db1d48c> in <lambda>(x)
      1 df = (pd.read_csv('C:\\Users\\wundermahn\Desktop\\aggregated_data.csv',
----> 2                     encoding = "ISO-8859-1", low_memory=False).apply(lambda x: x.str.strip() if (x.dtype == "object") else x))
      3 print(df.shape)
      4 
      5 label = df['ON_TIME']

c:\python367-64\lib\site-packages\pandas\core\generic.py in __getattr__(self, name)
   5268             or name in self._accessors
   5269         ):
-> 5270             return object.__getattribute__(self, name)
   5271         else:
   5272             if self._info_axis._can_hold_identifiers_and_holds_name(name):

c:\python367-64\lib\site-packages\pandas\core\accessor.py in __get__(self, obj, cls)
    185             # we're accessing the attribute of the class, i.e., Dataset.geo
    186             return self._accessor
--> 187         accessor_obj = self._accessor(obj)
    188         # Replace the property with the accessor object. Inspired by:
    189         # http://www.pydanny.com/cached-property.html

c:\python367-64\lib\site-packages\pandas\core\strings.py in __init__(self, data)
   2039 
   2040     def __init__(self, data):
-> 2041         self._inferred_dtype = self._validate(data)
   2042         self._is_categorical = is_categorical_dtype(data)
   2043         self._is_string = data.dtype.name == "string"

c:\python367-64\lib\site-packages\pandas\core\strings.py in _validate(data)
   2096 
   2097         if inferred_dtype not in allowed_types:
-> 2098             raise AttributeError("Can only use .str accessor with string values!")
   2099         return inferred_dtype
   2100 

**AttributeError: Can only use .str accessor with string values!**

因此,在尝试找到解决方法时,我偶然发现了这篇文章,其中建议使用:

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

但是,这并不会删除只包含空格或制表符的空单元格。

如何有效地去除所有变体的空白?我最终将删除具有超过 50% null 值的列。

【问题讨论】:

  • 你提前知道你的专栏是什么类型的吗?
  • 我没有。这就是问题所在——数据框是以sql 查询的形式提供给我的。我对数据完全不了解。并且形状大约是(401801, 267),因此尝试逐列遍历是相当麻烦的。对不起@RiccardoBucco

标签: python pandas whitespace trim


【解决方案1】:

您必须检查的不是列类型,而是每个 individual 值的类型, 所以代码可以是例如:

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

原因是:

  • 可以有object类型的列,
  • 在几乎所有单元格中都包含一个字符串
  • 但其中一些可以是 NaN,这是 float 的特例,因此 你不能在上面调用 strip

但是这样你不必要地执行类型列的代码 除了object,什么都不会改变。 如果这让您感到困扰,请仅对可能出现的列运行此代码 改变任何东西:

cols = df.select_dtypes(include='object').columns
df[cols] = df[cols].applymap(lambda x: x.strip() if type(x) == str else x)

【讨论】:

    【解决方案2】:

    首先使用select_dtypes 选择正确的列:

    # example dataframe
    df = pd.DataFrame({'col1':[1,2,3],
                       'col2':list('abc'),
                       'col3':[4.0, 5.0, 6.0],
                       'col4':[' foo', '   bar', 'foobar. ']})
    
       col1 col2  col3      col4
    0     1    a   4.0       foo
    1     2    b   5.0       bar
    2     3    c   6.0  foobar. 
    
    str_cols = df.select_dtypes('object').columns
    df[str_cols] = df[str_cols].apply(lambda x: x.str.strip())
    
    print(df)
       col1 col2  col3     col4
    0     1    a   4.0      foo
    1     2    b   5.0      bar
    2     3    c   6.0  foobar.
    

    【讨论】:

    • 您的方法类似于 OP。如果有一列包含例如列表值,它将失败。
    • 这是一次不错的尝试!我没有这样处理,但我发现object 列包含不同的值。例如,有时是A,有时是1,有时是" "
    【解决方案3】:

    你可以试试try

    def trim(x):
        try:
            return x.str.strip()
        except:
            return x
    
    df = df.apply(trim)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      • 2015-04-12
      • 2015-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多