J'ai une base de données de pandas avec une colonne 'cap'. Cette colonne est principalement composée de floats mais contient quelques chaînes, par exemple à l'index 2.
df =
cap
0 5.2
1 na
2 2.2
3 7.6
4 7.5
5 3.0
...
J'importe mes données depuis un fichier csv comme ceci:
df = DataFrame(pd.read_csv(myfile.file))
Malheureusement, lorsque je fais cela, la colonne 'cap' est importée entièrement en tant que chaîne. Je voudrais que les flotteurs soient identifiés comme flottants et les cordes comme des cordes. Essayer de convertir ceci en utilisant:
df['cap'] = df['cap'].astype(float)
génère une erreur:
could not convert string to float: na
Existe-t-il un moyen de transformer tous les nombres en flottants tout en conservant le "na" comme chaîne?
Voici une solution de contournement possible
d'abord, vous définissez une fonction qui convertit les nombres en nombre uniquement si nécessaire
def to_number(s):
try:
s1 = float(s)
return s1
except ValueError:
return s
et ensuite vous l'appliquez rangée par rangée.
Exemple:
donné
df
0
0 a
1 2
où a
et 2
sont des chaînes, nous effectuons la conversion via
converted = df.apply(lambda f : to_number(f[0]) , axis = 1)
converted
0 a
1 2
Un contrôle direct sur les types:
type(converted.iloc[0])
str
type(converted.iloc[1])
float
Les calculs avec des colonnes de type float64 (plutôt que d'objet) sont beaucoup plus efficaces, c'est donc préférable ... cela vous permettra également d'effectuer d'autres calculs. À cause de cela, il est recommandé d'utiliser NaN pour les données manquantes (plutôt que votre propre paramètre fictif ou Aucun).
In [11]: df.sum() # all strings
Out[11]:
cap 5.2na2.27.67.53.0
dtype: object
In [12]: df.apply(lambda f: to_number(f[0]), axis=1).sum() # floats and 'na' strings
TypeError: unsupported operand type(s) for +: 'float' and 'str'
Vous devriez utiliser convert_numeric pour contraindre à floats:
In [21]: df.convert_objects(convert_numeric=True)
Out[21]:
cap
0 5.2
1 NaN
2 2.2
3 7.6
4 7.5
5 3.0
Ou lisez-le directement en csv, en ajoutant 'na' à la liste des valeurs à considérer comme NaN:
In [22]: pd.read_csv(myfile.file, na_values=['na'])
Out[22]:
cap
0 5.2
1 NaN
2 2.2
3 7.6
4 7.5
5 3.0
Dans les deux cas, sum (et de nombreuses autres fonctions du pandas) fonctionnera désormais:
In [23]: df.sum()
Out[23]:
cap 25.5
dtype: float64
Comme Jeff conseille :
répéter 3 fois vite: objet == mauvais, float == bien
Tout d'abord, la manière dont vous importez votre fichier CSV est redondante, au lieu de:
df = DataFrame(pd.read_csv(myfile.file))
Vous pouvez faire directement:
df = pd.read_csv(myfile.file)
Puis convertir en float, et mettre tout ce qui n’est pas un nombre comme NaN:
df = pd.to_numeric(df, errors='coerce')
J'ai essayé une alternative sur ce qui précède:
for num, item in enumerate(data['col']):
try:
float(item)
except:
data['col'][num] = nan