剥离/修剪数据框架的所有字符串

清理 python/anda 中的多类型数据帧的值,我想修剪字符串。我现在按照两条指示来做:

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

这是相当缓慢的,我可以改善什么?

316561 次浏览

您可以使用 Series对象的 apply功能:

>>> 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的使用,因为 regex要快得多

另一个选项——使用 DataFrame 对象的 apply功能:

>>> 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

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

注意: 值不能是 types,如 dictslists,因为它们的 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()

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

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

但这样做应该更快:

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

你可以试试:

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())

金钱射击

下面是使用 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

工作范例

下面是一个由饰品托管的工作示例: Https://trinket.io/python3/e6ab7fb4ab

def trim(x):
if x.dtype == object:
x = x.str.split(' ').str[0]
return(x)


df = df.apply(trim)

(对于字符串列)怎么样

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

从不失败

单独的条带不会移除字符串中的内部额外空格。解决办法是首先用单个空间替换一个或多个空间。这样可以确保我们移除额外的内部空间和外部空间。

# Import packages
import re


# First inspect the dtypes of the dataframe
df.dtypes


# First replace one or more spaces with a single space. This ensures that we remove extra inner spaces and outer spaces.
df = df.applymap(lambda x: re.sub('\s+', ' ', x) if isinstance(x, str) else x)




# Then strip leading and trailing white spaces
df = df.apply(lambda x: x.str.strip() if isinstance(x, object) else x)

@ Jezrael 答案看起来不错。但是,如果希望在最终结果集中返回其他(数字/整数等)列,那么应该需要与原始 DataFrame 合并。

如果是这种情况,那么你可以使用这种方法,

df = df.apply(lambda x: x.str.strip() if x.dtype.name == 'object' else x, axis=0)

谢谢!

最佳答案的基准:

bm = Benchmark()
df = pd.read_excel(
path,
sheet_name=advantage_sheet_name,
parse_dates=True
)
bm.mark('Loaded')


# @jezrael 's answer (accepted answer)
dfClean_1 = df\
.select_dtypes(['object'])\
.apply(lambda x: x.str.strip())
bm.mark('Clean method 1')


# @Jonathan B. answer
dfClean_2 = df\
.applymap(lambda x: x.strip() if isinstance(x, str) else x)
bm.mark('Clean method 2')


#@MaxU - stop genocide of UA / @Roman Pekar answer
dfClean_3 = df\
.replace(r'\s*(.*?)\s*', r'\1', regex=True)
bm.mark('Clean method 3')

结果

145.734375 - 145.734375 : Loaded
147.765625 - 2.03125 : Clean method 1
155.109375 - 7.34375 : Clean method 2
288.953125 - 133.84375 : Clean method 3