Parfois, lorsque des données sont importées dans Pandas Dataframe, elles sont toujours importées sous le type object
. Cela convient très bien à la plupart des opérations, mais j'essaie de créer une fonction d'exportation personnalisée et ma question est la suivante:
Je sais que je peux dire aux Pandas qu'il s'agit d'un type int, str, etc., mais je ne souhaite pas le faire. J'espérais que les pandas seraient suffisamment intelligents pour connaître tous les types de données lorsqu'un utilisateur importe ou ajoute une colonne .
EDIT - exemple d'importation
a = ['a']
col = ['somename']
df = pd.DataFrame(a, columns=col)
print(df.dtypes)
>>> somename object
dtype: object
Le type doit être string?
Il ne s'agit que d'une réponse partielle, mais vous pouvez obtenir des comptes de fréquence du type de données des éléments d'une variable sur l'ensemble du DataFrame, comme suit:
dtypeCount =[df.iloc[:,i].apply(type).value_counts() for i in range(df.shape[1])]
Cela retourne
dtypeCount
[<class 'numpy.int32'> 4
Name: a, dtype: int64,
<class 'int'> 2
<class 'str'> 2
Name: b, dtype: int64,
<class 'numpy.int32'> 4
Name: c, dtype: int64]
Cela ne l’imprime pas très bien, mais vous pouvez extraire des informations pour n’importe quelle variable par emplacement:
dtypeCount[1]
<class 'int'> 2
<class 'str'> 2
Name: b, dtype: int64
ce qui devrait vous aider à déterminer quels types de données sont à l'origine du problème et combien il en existe.
Vous pouvez ensuite inspecter les lignes qui ont un objet str dans la seconde variable en utilisant
df[df.iloc[:,1].map(lambda x: type(x) == str)]
a b c
1 1 n 4
3 3 g 6
Les données
df = DataFrame({'a': range(4),
'b': [6, 'n', 7, 'g'],
'c': range(3, 7)})
Vous pouvez également déduire les objets après avoir déposé des éléments non pertinents à l'aide de infer_objects()
. Vous trouverez ci-dessous un exemple général.
df_orig = pd.DataFrame({"A": ["a", 1, 2, 3], "B": ["b", 1.2, 1.8, 1.8]})
df = df_orig.iloc[1:].infer_objects()
print(df_orig.dtypes, df.dtypes, sep='\n\n')
Sortie:
Voici un (pas parfait) essayez d’écrire une meilleure inférence. Lorsque vous avez déjà des données dans votre base de données, l'inférence devinera le type de plus petit possible. Il manque actuellement la date et l'heure, mais je pense que cela pourrait être un point de départ. Avec cette inférence, je peux récupérer 70% de la mémoire utilisée.
def infer_df(df, hard_mode=False, float_to_int=False, mf=None):
ret = {}
# ToDo: How much does auto convertion cost
# set multiplication factor
mf = 1 if hard_mode else 0.5
# set supported datatyp
integers = ['int8', 'int16', 'int32', 'int64']
floats = ['float16', 'float32', 'float64']
# ToDo: Unsigned Integer
# generate borders for each datatype
b_integers = [(np.iinfo(i).min, np.iinfo(i).max, i) for i in integers]
b_floats = [(np.finfo(f).min, np.finfo(f).max, f) for f in floats]
for c in df.columns:
_type = df[c].dtype
# if a column is set to float, but could be int
if float_to_int and np.issubdtype(_type, np.floating):
if np.sum(np.remainder(df[c], 1)) == 0:
df[c] = df[c].astype('int64')
_type = df[c].dtype
# convert type of column to smallest possible
if np.issubdtype(_type, np.integer) or np.issubdtype(_type, np.floating):
borders = b_integers if np.issubdtype(_type, np.integer) else b_floats
_min = df[c].min()
_max = df[c].max()
for b in borders:
if b[0] * mf < _min and _max < b[1] * mf:
ret[c] = b[2]
break
if _type == 'object' and len(df[c].unique()) / len(df) < 0.1:
ret[c] = 'category'
return ret