NumPy सरणी JSON अनुक्रमिक नहीं है


247

एक NumPy सरणी बनाने, और इसे Django संदर्भ चर के रूप में सहेजने के बाद, मुझे वेबपृष्ठ लोड करते समय निम्न त्रुटि प्राप्त होती है:

array([   0,  239,  479,  717,  952, 1192, 1432, 1667], dtype=int64) is not JSON serializable

इसका क्या मतलब है?


19
इसका मतलब यह है कि कहीं न कहीं, कुछ jsonमॉड्यूल का उपयोग करके एक खस्ता सरणी को डंप करने की कोशिश कर रहा है । लेकिन numpy.ndarrayएक प्रकार नहीं है जो jsonजानता है कि कैसे संभालना है। आपको या तो अपना खुद का सीरियल लिखने की आवश्यकता होगी, या (और अधिक) बस list(your_array)जो कुछ भी लिख रहा है उसे पास करें।
mgilson

24
नोट list(your_array)हमेशा काम नहीं करेगा क्योंकि यह सुन्न चींटियों को लौटाता है, देशी चींटियों को नहीं। your_array.to_list()इसके बजाय उपयोग करें ।
ashishsingal

18
@ ashishsingal की टिप्पणी के बारे में एक टिप्पणी, यह आपका_अरे.टोलिस्ट () होना चाहिए, न कि_सूची ()।
वेगा

जवाबों:


289

मैं नियमित रूप से "jsonify" np.arrays करता हूं। इस तरह से पहले सरणियों पर ".tolist ()" विधि का उपयोग करने का प्रयास करें:

import numpy as np
import codecs, json 

a = np.arange(10).reshape(2,5) # a 2 by 5 array
b = a.tolist() # nested lists with same data, indices
file_path = "/path.json" ## your path variable
json.dump(b, codecs.open(file_path, 'w', encoding='utf-8'), separators=(',', ':'), sort_keys=True, indent=4) ### this saves the array in .json format

सरणी उपयोग को "अनसुनी" करने के लिए:

obj_text = codecs.open(file_path, 'r', encoding='utf-8').read()
b_new = json.loads(obj_text)
a_new = np.array(b_new)

3
इसे केवल सूचियों की सूची के रूप में क्यों संग्रहीत किया जा सकता है?
निखिल प्रभु

मैं नहीं जानता कि लेकिन मैं np.array प्रकार की उम्मीद मेटाडाटा कि json में फ़िट नहीं होता है (उदाहरण के लिए वे नाव की तरह प्रत्येक प्रविष्टि के डेटा प्रकार निर्दिष्ट करें)
travelingbones

2
मैंने आपकी विधि की कोशिश की, लेकिन ऐसा लगता है कि यह कार्यक्रम अटक गया tolist()
हरवेट

3
@frankliuao मैंने पाया कि tolist()डेटा बड़ी होने पर भारी मात्रा में समय लगता है।
हरवेट

4
@ निखिलप्रभु जासन जावास्क्रिप्ट ऑब्जेक्ट नोटेशन है, और इसलिए केवल जावास्क्रिप्ट भाषा से बुनियादी निर्माणों का प्रतिनिधित्व कर सकते हैं: ऑब्जेक्ट्स (पायथन डाइट्स के अनुरूप), सरणियाँ (पायथन लिस्ट्स के अनुरूप), संख्या, बूलियन, स्ट्रिंग्स और नॉल्स (पायथन नॉट्स के अनुरूप) )। Numpy सरणियाँ उन चीजों में से कोई भी नहीं हैं, और इसलिए JSON में क्रमबद्ध नहीं किया जा सकता है। कुछ को जेएसओ जैसे फॉर्म (सूचियों की सूची) में परिवर्तित किया जा सकता है, जो कि यह उत्तर देता है।
क्रिस एल। बार्न्स

225

JSON को एक numpy.ndarray या किसी नेस्टेड-सूची संरचना के रूप में संग्रहीत करें।

class NumpyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.ndarray):
            return obj.tolist()
        return json.JSONEncoder.default(self, obj)

a = np.array([[1, 2, 3], [4, 5, 6]])
print(a.shape)
json_dump = json.dumps({'a': a, 'aa': [2, (2, 3, 4), a], 'bb': [2]}, cls=NumpyEncoder)
print(json_dump)

उत्पादन होगा:

(2, 3)
{"a": [[1, 2, 3], [4, 5, 6]], "aa": [2, [2, 3, 4], [[1, 2, 3], [4, 5, 6]]], "bb": [2]}

JSON से पुनर्स्थापित करने के लिए:

json_load = json.loads(json_dump)
a_restored = np.asarray(json_load["a"])
print(a_restored)
print(a_restored.shape)

उत्पादन होगा:

[[1 2 3]
 [4 5 6]]
(2, 3)

26
यह बोर्ड के उच्चतर तरीके से होना चाहिए, यह ऐसा करने का सामान्य और उचित रूप से अमूर्त तरीका है। धन्यवाद!

2
क्या सूची से ndarray वापस पाने का एक सरल तरीका है?
DarksteelPenguin

5
@DarksteelPenguin आप देख रहे हैं numpy.asarray()?
एओलस

3
यह उत्तर बहुत अच्छा है और आसानी से खसरा फ्लोट 32 और np.float64 मूल्यों को जौन के रूप में क्रमबद्ध करने के लिए बढ़ाया जा सकता है:if isinstance(obj, np.float32) or isinstance(obj, np.float64): return float(obj)
बेंसगे

यह समाधान आपको सूची में मैन्युअल रूप से प्रत्येक सुपीरियर सरणी में डालने से बचता है।
एडुआर्डोसुफैन

44

आप पंडों का उपयोग कर सकते हैं :

import pandas as pd
pd.Series(your_array).to_json(orient='values')

6
महान! और मुझे लगता है कि 2D np.array के लिए यह कुछ ऐसा होगा pd.DataFrame(your_array).to_json('data.json', orient='split')
निक्स

2
दिन बचा लिया। धन्यवाद
अनुराग

40

मुझे सबसे अच्छा समाधान मिला यदि आपने एक शब्दकोश में सुन्न सरणियों का नेस्ट किया है:

import json
import numpy as np

class NumpyEncoder(json.JSONEncoder):
    """ Special json encoder for numpy types """
    def default(self, obj):
        if isinstance(obj, np.integer):
            return int(obj)
        elif isinstance(obj, np.floating):
            return float(obj)
        elif isinstance(obj, np.ndarray):
            return obj.tolist()
        return json.JSONEncoder.default(self, obj)

dumped = json.dumps(data, cls=NumpyEncoder)

with open(path, 'w') as f:
    json.dump(dumped, f)

इस आदमी को धन्यवाद ।


उपयोगी उत्तर के लिए धन्यवाद! मैंने एक json फ़ाइल के लिए विशेषताएँ लिखीं, लेकिन अब मुझे लॉजिस्टिक रिग्रेशन के मापदंडों को पढ़ने में परेशानी हो रही है। वहाँ इस बचाया जोंस फ़ाइल के लिए एक 'डिकोडर' है?
TTZ

बेशक, jsonपीछे पढ़ने के लिए आप इसका उपयोग कर सकते हैं: with open(path, 'r') as f: data = json.load(f)जो आपके डेटा के साथ एक शब्दकोश देता है।
tsveti_iko

यह jsonफ़ाइल पढ़ने के लिए है और फिर इसे आउटपुट के लिए data = json.loads(data)
डीरिएरलाइज़ करने के

मुझे बाइट्स डेटाटाइप को हैंडल करने के लिए इसे जोड़ना था .. मानकर सभी बाइट्स utf-8 स्ट्रिंग हैं। एलिफ इनस्टेंस (obj, (बाइट्स))): रिटर्न obj.decode ("utf-8")
सोइची हयाशी

+1। हमें "डिफ डिफ़ॉल्ट (आत्म, obj)" के अंत में लाइन "रिटर्न जोंस। जेएसओएनसीओडर (स्व, ओब्ज)" की आवश्यकता क्यों है?
हंस

23

json.dumps defaultKwarg का उपयोग करें :

डिफ़ॉल्ट एक फ़ंक्शन होना चाहिए जो उन वस्तुओं के लिए कहा जाता है जो अन्यथा क्रमबद्ध नहीं हो सकते हैं।

में defaultसमारोह की जांच करता है, तो वस्तु, मॉड्यूल numpy से है, इसलिए या तो उपयोग करता है, तो ndarray.tolistएक के लिए ndarrayया उपयोग .itemकिसी अन्य numpy विशिष्ट प्रकार के लिए।

import numpy as np

def default(obj):
    if type(obj).__module__ == np.__name__:
        if isinstance(obj, np.ndarray):
            return obj.tolist()
        else:
            return obj.item()
    raise TypeError('Unknown type:', type(obj))

dumped = json.dumps(data, default=default)

type(obj).__module__ == np.__name__: वहां रेखा की क्या भूमिका है ? क्या यह उदाहरण के लिए जाँच करने के लिए पर्याप्त नहीं होगा?
रेमन मार्टिनेज

@RamonMartinez, यह जानने के लिए कि ऑब्जेक्ट एक संख्यात्मक ऑब्जेक्ट है, इस तरह से मैं .itemलगभग किसी भी संख्यात्मक ऑब्जेक्ट के लिए उपयोग कर सकता हूं। defaultफ़ंक्शन json.dumpsको क्रमबद्ध करने के सभी अज्ञात प्रकार के प्रयासों के लिए कहा जाता है । न केवल सुन्न
मोशेवी

5

यह डिफ़ॉल्ट रूप से समर्थित नहीं है, लेकिन आप इसे आसानी से काम कर सकते हैं! यदि आप एक ही डेटा वापस चाहते हैं तो कई चीजें हैं जिन्हें आप एनकोड करना चाहेंगे:

  • डेटा, जिसे आप obj.tolist()उल्लिखित @travelingbones के रूप में प्राप्त कर सकते हैं । कभी-कभी यह काफी अच्छा हो सकता है।
  • डेटा प्रकार। मुझे लगता है कि यह कुछ मामलों में महत्वपूर्ण है।
  • आयाम (जरूरी नहीं कि 2 डी), जो ऊपर से प्राप्त किया जा सकता है यदि आप मानते हैं कि इनपुट वास्तव में हमेशा एक 'आयताकार' ग्रिड है।
  • मेमोरी ऑर्डर (पंक्ति- या स्तंभ-प्रमुख)। यह अक्सर बात नहीं करता है, लेकिन कभी-कभी यह (उदाहरण के प्रदर्शन) करता है, तो सब कुछ क्यों नहीं बचा?

इसके अलावा, आपकी संख्या आपके सरणी डेटा संरचना का हिस्सा हो सकती है, उदाहरण के लिए आपके पास कुछ मैट्रिसेस के साथ एक सूची है। उसके लिए आप एक कस्टम एनकोडर का उपयोग कर सकते हैं जो मूल रूप से ऊपर करता है।

किसी समाधान को लागू करने के लिए यह पर्याप्त होना चाहिए। या आप json-tricks का उपयोग कर सकते हैं जो कि यह (और विभिन्न अन्य प्रकारों का समर्थन करता है) (अस्वीकरण: मैंने इसे बनाया)।

pip install json-tricks

फिर

data = [
    arange(0, 10, 1, dtype=int).reshape((2, 5)),
    datetime(year=2017, month=1, day=19, hour=23, minute=00, second=00),
    1 + 2j,
    Decimal(42),
    Fraction(1, 3),
    MyTestCls(s='ub', dct={'7': 7}),  # see later
    set(range(7)),
]
# Encode with metadata to preserve types when decoding
print(dumps(data))

3

मुझे कुछ समान संख्या में एक नेस्टेड डिक्शनरी के साथ एक समान समस्या थी।

def jsonify(data):
    json_data = dict()
    for key, value in data.iteritems():
        if isinstance(value, list): # for lists
            value = [ jsonify(item) if isinstance(item, dict) else item for item in value ]
        if isinstance(value, dict): # for nested lists
            value = jsonify(value)
        if isinstance(key, int): # if key is integer: > to string
            key = str(key)
        if type(value).__module__=='numpy': # if value is numpy.*: > to python list
            value = value.tolist()
        json_data[key] = value
    return json_data

3

आप defaultउदाहरण के लिए तर्क का उपयोग भी कर सकते हैं :

def myconverter(o):
    if isinstance(o, np.float32):
        return float(o)

json.dump(data, default=myconverter)

1

इसके अलावा, पायथन ~> में सूची बनाम सरणियों पर कुछ बहुत ही रोचक जानकारी पायथन लिस्ट बनाम एरे - कब उपयोग करना है?

यह ध्यान दिया जा सकता है कि एक बार जब मैं JSON फ़ाइल में सहेजने से पहले अपनी सरणियों को एक सूची में परिवर्तित करता हूं, तो मेरी तैनाती में अभी, वैसे भी, एक बार जब मैंने पढ़ा कि JSON फ़ाइल को बाद में उपयोग करने के लिए, मैं इसे सूची रूप में उपयोग करना जारी रख सकता हूं (जैसे यह एक सरणी में वापस परिवर्तित करने का विरोध किया)।

और वास्तव में इस तरह से एक सूची (अल्पविराम से अलग) बनाम एक सरणी (नहीं-अल्पविराम अलग) के रूप में स्क्रीन पर अच्छे (मेरे विचार में) दिखता है।

ऊपर @ travelbones's .tolist () विधि का उपयोग करते हुए, मैं इस तरह का उपयोग कर रहा हूं (कुछ त्रुटियां जो मैंने भी पाई हैं, उन्हें पकड़ना):

बचाने के लिए

def writeDict(values, name):
    writeName = DIR+name+'.json'
    with open(writeName, "w") as outfile:
        json.dump(values, outfile)

पढ़ें समाचार

def readDict(name):
    readName = DIR+name+'.json'
    try:
        with open(readName, "r") as infile:
            dictValues = json.load(infile)
            return(dictValues)
    except IOError as e:
        print(e)
        return('None')
    except ValueError as e:
        print(e)
        return('None')

उम्मीद है की यह मदद करेगा!


1

यहां एक कार्यान्वयन है जो मेरे लिए काम करता है और सभी नंस को हटा दिया गया है (यह मानते हुए कि ये साधारण वस्तु (सूची या तानाशाह) हैं):

from numpy import isnan

def remove_nans(my_obj, val=None):
    if isinstance(my_obj, list):
        for i, item in enumerate(my_obj):
            if isinstance(item, list) or isinstance(item, dict):
                my_obj[i] = remove_nans(my_obj[i], val=val)

            else:
                try:
                    if isnan(item):
                        my_obj[i] = val
                except Exception:
                    pass

    elif isinstance(my_obj, dict):
        for key, item in my_obj.iteritems():
            if isinstance(item, list) or isinstance(item, dict):
                my_obj[key] = remove_nans(my_obj[key], val=val)

            else:
                try:
                    if isnan(item):
                        my_obj[key] = val
                except Exception:
                    pass

    return my_obj

1

यह एक अलग उत्तर है, लेकिन यह उन लोगों की मदद करने में मदद कर सकता है जो डेटा को बचाने की कोशिश कर रहे हैं और फिर इसे पढ़ सकते हैं।
इसमें अचार होता है जो अचार की तुलना में तेज़ और आसान होता है।
मैंने अचार डंप में इसे बचाने और पढ़ने की कोशिश की, लेकिन पढ़ते समय बहुत समस्याएं थीं और एक घंटा बर्बाद हो गया और अभी भी समाधान नहीं मिला, हालांकि मैं चैट बॉट बनाने के लिए अपने स्वयं के डेटा पर काम कर रहा था।

vec_xऔर vec_yपर्याप्त सरणियाँ हैं:

data=[vec_x,vec_y]
hkl.dump( data, 'new_data_file.hkl' )

तब आप इसे पढ़ते हैं और संचालन करते हैं:

data2 = hkl.load( 'new_data_file.hkl' )

1

जाँच प्रकार के साथ लूप के लिए सरल हो सकता है:

with open("jsondontdoit.json", 'w') as fp:
    for key in bests.keys():
        if type(bests[key]) == np.ndarray:
            bests[key] = bests[key].tolist()
            continue
        for idx in bests[key]:
            if type(bests[key][idx]) == np.ndarray:
                bests[key][idx] = bests[key][idx].tolist()
    json.dump(bests, fp)
    fp.close()

1

NumpyEncoder का उपयोग करें यह json डंप को सफलतापूर्वक संसाधित करेगा। फेंकने के बाद - NumPy सरणी JSON युग्मित नहीं है

import numpy as np
import json
from numpyencoder import NumpyEncoder
arr = array([   0,  239,  479,  717,  952, 1192, 1432, 1667], dtype=int64) 
json.dumps(arr,cls=NumpyEncoder)

0

TypeError: array ([[0.46872085, 0.67374235, 1.0218339, 0.13210179, 0.5440686, 0.9140083, 0.58720225, 0.2199381]], dtype = float32) JSON से सीरियल करने योग्य नहीं है

जब मैंने json फॉर्मेट में प्रतिक्रिया की अपेक्षा की थी तब मैंने उपर्युक्त त्रुटि को फेंक दिया था, जब मैंने डेटा की सूची को model.predict () में पास करने की कोशिश की।

> 1        json_file = open('model.json','r')
> 2        loaded_model_json = json_file.read()
> 3        json_file.close()
> 4        loaded_model = model_from_json(loaded_model_json)
> 5        #load weights into new model
> 6        loaded_model.load_weights("model.h5")
> 7        loaded_model.compile(optimizer='adam', loss='mean_squared_error')
> 8        X =  [[874,12450,678,0.922500,0.113569]]
> 9        d = pd.DataFrame(X)
> 10       prediction = loaded_model.predict(d)
> 11       return jsonify(prediction)

लेकिन सौभाग्य से उस त्रुटि को हल करने का संकेत मिला जो फेंक रही थी। वस्तुओं का क्रमांकन केवल निम्न रूपांतरण के लिए लागू होता है मैपिंग निम्न तरीके से होनी चाहिए वस्तु - तानाशाही सरणी - सूची स्ट्रिंग - स्ट्रिंग पूर्णांक - पूर्णांक

यदि आप लाइन नंबर 10 की भविष्यवाणी देखने के लिए ऊपर स्क्रॉल करते हैं = load_model.predict (d) जहां कोड की यह लाइन प्रकार सरणी डेटाटाइप का आउटपुट उत्पन्न कर रही थी, जब आप सरणी को जोंस प्रारूप में बदलने की कोशिश करते हैं तो यह संभव नहीं है।

अंत में मैंने कोड की पंक्तियों का अनुसरण करके प्राप्त आउटपुट को टाइप सूची में परिवर्तित करके समाधान पाया

prediction = load_model.predict (d)
listtype = prediction.tolist () रिटर्न jsonify (listtype)

Bhoom! अंत में अपेक्षित उत्पादन मिला, यहां छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.