web-dev-qa-db-fra.com

Convertir le type numpy en python

J'ai une liste de dict sous la forme suivante que je génère à partir de pandas. Je veux le convertir au format json.

list_val = [{1.0: 685}, {2.0: 8}]
output = json.dumps(list_val)

Cependant, json.dumps génère une erreur: TypeError: 685 n'est pas sérialisable JSON

Je suppose que c'est un problème de conversion de type de numpy en python (?).

Cependant, lorsque je convertis les valeurs v de chaque dict du tableau à l'aide de np.int32 (v), il renvoie toujours l'erreur.

EDIT: Voici le code complet

            new = df[df[label] == label_new] 
            ks_dict = json.loads(content)
            ks_list = ks_dict['variables']
            freq_counts = []

            for ks_var in ks_list:

                    freq_var = dict()
                    freq_var["name"] = ks_var["name"]
                    ks_series = new[ks_var["name"]]
                    temp_df = ks_series.value_counts().to_dict()
                    freq_var["new"] = [{u: np.int32(v)} for (u, v) in temp_df.iteritems()]            
                    freq_counts.append(freq_var)

           out = json.dumps(freq_counts)
35
ubh

Il semble que vous ayez raison:

>>> import numpy
>>> import json
>>> json.dumps(numpy.int32(685))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/json/__init__.py", line 243, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python2.7/json/encoder.py", line 184, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: 685 is not JSON serializable

La chose malheureuse ici est que les nombres numpy '__repr__ ne vous donne aucune indication sur le type qu'ils sont. Ils courent en se faisant passer pour ints quand ils ne le sont pas ( halètement ). En fin de compte, il semble que json vous indique qu'un int n'est pas sérialisable, mais vraiment, il vous dit que ce np.int32 particulier (ou tout autre type que vous avez réellement) ne l'est pas sérialisable. (Pas de vraie surprise là-bas - Aucun np.int32 n'est sérialisable). C'est aussi pourquoi le dict que vous avez inévitablement imprimé avant de le passer à json.dumps on dirait qu'il contient aussi des entiers.

La solution de contournement la plus simple ici est probablement de écrire votre propre sérialiseur1:

class MyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, numpy.integer):
            return int(obj)
        Elif isinstance(obj, numpy.floating):
            return float(obj)
        Elif isinstance(obj, numpy.ndarray):
            return obj.tolist()
        else:
            return super(MyEncoder, self).default(obj)

Vous l'utilisez comme ceci:

json.dumps(numpy.float32(1.2), cls=MyEncoder)
json.dumps(numpy.arange(12), cls=MyEncoder)
json.dumps({'a': numpy.int32(42)}, cls=MyEncoder)

etc.

1Ou vous pouvez simplement écrire la fonction par défaut et la passer comme argument de mot clé defaut à json.dumps. Dans ce scénario, vous remplaceriez la dernière ligne par raise TypeError, mais ... meh. La classe est plus extensible :-)

92
mgilson

Vous pouvez également convertir le tableau en une liste python (utilisez la méthode tolist)), puis convertir la liste en json.

4
Emanuele Paolini

Si vous laissez les données dans l'un des objets pandas, la bibliothèque fournit un to_json fonctionne sur Series, DataFrame et tous les autres cousins ​​de dimension supérieure.

Voir Series.to_json ()

1
mobiusklein

Vous pouvez utiliser notre fork d'ujson pour gérer NumPy int64. caiyunapp/ultrajson: décodeur et encodeur JSON ultra rapide écrit en C avec Python et liaisons NumPy

pip install nujson

Ensuite

>>> import numpy as np
>>> import nujson as ujson
>>> a = {"a": np.int64(100)}
>>> ujson.dumps(a)
'{"a":100}'
>>> a["b"] = np.float64(10.9)
>>> ujson.dumps(a)
'{"a":100,"b":10.9}'
>>> a["c"] = np.str_("12")
>>> ujson.dumps(a)
'{"a":100,"b":10.9,"c":"12"}'
>>> a["d"] = np.array(list(range(10)))
>>> ujson.dumps(a)
'{"a":100,"b":10.9,"c":"12","d":[0,1,2,3,4,5,6,7,8,9]}'
>>> a["e"] = np.repeat(3.9, 4)
>>> ujson.dumps(a)
'{"a":100,"b":10.9,"c":"12","d":[0,1,2,3,4,5,6,7,8,9],"e":[3.9,3.9,3.9,3.9]}'
1
ringsaturn