Je lis un fichier CSV dans un DataFrame. J'ai besoin de supprimer les espaces de toutes les cellules ressemblant à des chaînes, en laissant les autres cellules inchangées dans Python 2.7.
Voici ce que je fais:
def remove_whitespace( x ):
if isinstance( x, basestring ):
return x.strip()
else:
return x
my_data = my_data.applymap( remove_whitespace )
Y a-t-il une meilleure façon ou plus idiomatique aux Pandas de le faire?
Existe-t-il un moyen plus efficace (peut-être en faisant les choses en termes de colonne)?
J'ai essayé de chercher une réponse définitive, mais la plupart des questions sur ce sujet semblent porter sur la suppression des espaces dans les noms de colonnes, ou sur l'hypothèse que les cellules sont toutes des chaînes.
Je suis tombé sur cette question en cherchant un extrait rapide et minimaliste que je pourrais utiliser. Je devais en assembler moi-même à partir des messages ci-dessus. Peut-être que quelqu'un trouvera cela utile:
data_frame_trimmed = data_frame.apply(lambda x: x.str.strip() if x.dtype == "object" else x)
Vous pouvez utiliser la méthode Series.str.strip()
de pandas pour le faire rapidement pour chaque colonne de type chaîne:
>>> 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
Lorsque vous appelez pandas.read_csv
, vous pouvez utiliser une expression régulière qui correspond à zéro ou plusieurs espaces suivi d'une virgule suivie de zéro ou plusieurs espaces en tant que délimiteur.
Par exemple, voici "data.csv"
:
In [19]: !cat data.csv
1.5, aaa, bbb , ddd , 10 , XXX
2.5, eee, fff , ggg, 20 , YYY
(La première ligne se termine par trois espaces après XXX
, tandis que la deuxième ligne se termine par la dernière Y
.)
Ce qui suit utilise pandas.read_csv()
pour lire les fichiers, avec l’expression régulière ' *, *'
comme délimiteur. (L'utilisation d'une expression régulière comme délimiteur n'est disponible que dans le moteur "python" de read_csv()
.)
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
La réponse "data ['values']. Str.strip ()" ci-dessus n'a pas fonctionné pour moi, mais j'ai trouvé un moyen simple de contourner le problème. Je suis sûr qu'il existe un meilleur moyen de le faire. La fonction str.strip () fonctionne sur Series. Ainsi, j'ai converti la colonne dataframe en une série, enlevé les espaces, remplacé la colonne convertie dans le dataframe. Voici l'exemple de code.
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)
J'ai trouvé le code suivant utile et quelque chose qui aiderait probablement les autres. Cet extrait de code vous permettra de supprimer des espaces dans une colonne ainsi que dans l'ensemble du DataFrame, selon votre cas d'utilisation.
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)
Cela a fonctionné pour moi - l'applique à l'ensemble du cadre de données:
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))
Voici une solution colonne par pandas avec:
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)
Cela convertira les valeurs des colonnes de type d'objet en chaîne. Devrait prendre des précautions avec les colonnes de type mixte. Par exemple, si votre colonne contient des codes postaux avec 20001 et «21110», vous obtiendrez «20001» et «21110».