Je veux définir les dtype
s de plusieurs colonnes dans pd.Dataframe
(j'ai un fichier que j'ai dû analyser manuellement dans une liste de listes, car le fichier n'était pas prêt pour pd.read_csv
)
import pandas as pd
print pd.DataFrame([['a','1'],['b','2']],
dtype={'x':'object','y':'int'},
columns=['x','y'])
Je reçois
ValueError: entry not a 2- or 3- Tuple
Le seul moyen de les définir consiste à parcourir en boucle chaque variable de colonne et à procéder à une refonte avec astype
.
dtypes = {'x':'object','y':'int'}
mydata = pd.DataFrame([['a','1'],['b','2']],
columns=['x','y'])
for c in mydata.columns:
mydata[c] = mydata[c].astype(dtypes[c])
print mydata['y'].dtype #=> int64
Y a-t-il un meilleur moyen?
Depuis 0.17, vous devez utiliser les conversions explicites:
pd.to_datetime, pd.to_timedelta and pd.to_numeric
(Comme mentionné ci-dessous, plus de "magie", convert_objects
est obsolète en 0.17)
df = pd.DataFrame({'x': {0: 'a', 1: 'b'}, 'y': {0: '1', 1: '2'}, 'z': {0: '2018-05-01', 1: '2018-05-02'}})
df.dtypes
x object
y object
z object
dtype: object
df
x y z
0 a 1 2018-05-01
1 b 2 2018-05-02
Vous pouvez les appliquer à chaque colonne à convertir:
df["y"] = pd.to_numeric(df["y"])
df["z"] = pd.to_datetime(df["z"])
df
x y z
0 a 1 2018-05-01
1 b 2 2018-05-02
df.dtypes
x object
y int64
z datetime64[ns]
dtype: object
et confirmez que le type est mis à jour.
RÉPONSE ANCIENNE/PÉRIMÉE des pandas 0.12 - 0.16: Vous pouvez utiliser convert_objects
pour déduire de meilleurs types:
In [21]: df
Out[21]:
x y
0 a 1
1 b 2
In [22]: df.dtypes
Out[22]:
x object
y object
dtype: object
In [23]: df.convert_objects(convert_numeric=True)
Out[23]:
x y
0 a 1
1 b 2
In [24]: df.convert_objects(convert_numeric=True).dtypes
Out[24]:
x object
y int64
dtype: object
La magie! (Triste de le voir obsolète.)
Pour ceux qui viennent de Google (etc.) comme moi:
convert_objects
est obsolète depuis le 0.17 - si vous l'utilisez, vous recevez un avertissement comme celui-ci:
FutureWarning: convert_objects is deprecated. Use the data-type specific converters
pd.to_datetime, pd.to_timedelta and pd.to_numeric.
Vous devriez faire quelque chose comme ce qui suit:
df =
df.astype(np.float)
df["A"] =
pd.to_numeric(df["A"])
vous pouvez définir les types explicitement avec pandas DataFrame.astype(dtype, copy=True, raise_on_error=True, **kwargs)
et transmettre un dictionnaire avec les types que vous souhaitez dtype
voici un exemple:
import pandas as pd
wheel_number = 5
car_name = 'jeep'
minutes_spent = 4.5
# set the columns
data_columns = ['wheel_number', 'car_name', 'minutes_spent']
# create an empty dataframe
data_df = pd.DataFrame(columns = data_columns)
df_temp = pd.DataFrame([[wheel_number, car_name, minutes_spent]],columns = data_columns)
data_df = data_df.append(df_temp, ignore_index=True)
In [11]: data_df.dtypes
Out[11]:
wheel_number float64
car_name object
minutes_spent float64
dtype: object
data_df = data_df.astype(dtype= {"wheel_number":"int64",
"car_name":"object","minutes_spent":"float64"})
maintenant vous pouvez voir que ça a changé
In [18]: data_df.dtypes
Out[18]:
wheel_number int64
car_name object
minutes_spent float64
Une autre façon de définir les types de colonne consiste à créer tout d'abord un tableau numpy record avec les types souhaités, à le compléter puis à le transmettre à un constructeur DataFrame.
import pandas as pd
import numpy as np
x = np.empty((10,), dtype=[('x', np.uint8), ('y', np.float64)])
df = pd.DataFrame(x)
df.dtypes ->
x uint8
y float64
Il vaut mieux utiliser np.arrays, puis passer les noms de données et de colonnes sous forme de dictionnaire.
import numpy as np
import pandas as pd
# Feature: np arrays are 1: efficient, 2: can be pre-sized
x = np.array(['a', 'b'], dtype=object)
y = np.array([ 1 , 2 ], dtype=np.int32)
df = pd.DataFrame({
'x' : x, # Feature: column name is near data array
'y' : y,
}
)
face à un problème similaire à vous. Dans mon cas, j'ai des milliers de fichiers de journaux de Cisco que je dois analyser manuellement.
Afin d'être flexible avec les champs et les types, j'ai testé avec succès l'utilisation de StringIO + read_cvs qui accepte effectivement un dict pour la spécification dtype.
Je reçois habituellement chacun des fichiers (5 à 20k lignes) dans un tampon et crée les dictionnaires dtype dynamiquement.
Finalement, je concatène (de manière catégorique ... grâce à 0.19) ces images en un grand bloc de données que je sauvegarde en hdf5.
Quelque chose dans ce sens
import pandas as pd
import io
output = io.StringIO()
output.write('A,1,20,31\n')
output.write('B,2,21,32\n')
output.write('C,3,22,33\n')
output.write('D,4,23,34\n')
output.seek(0)
df=pd.read_csv(output, header=None,
names=["A","B","C","D"],
dtype={"A":"category","B":"float32","C":"int32","D":"float64"},
sep=","
)
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 4 columns):
A 5 non-null category
B 5 non-null float32
C 5 non-null int32
D 5 non-null float64
dtypes: category(1), float32(1), float64(1), int32(1)
memory usage: 205.0 bytes
None
Pas très pythonique .... mais fait le travail
J'espère que ça aide.
JC