web-dev-qa-db-fra.com

Détermination du type de données de colonne Pandas

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:

  • Existe-t-il un moyen de forcer les pandas à déduire les types de données des données d'entrée?
  • Sinon, y a-t-il un moyen, après le chargement des données, d'inférer les types de données d'une manière ou d'une autre?

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? 

11
code base 5000

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)})
15
lmo

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:

 output print

1
shahar_m

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