NumPy অ্যারে JSON সিরিয়ালাইজযোগ্য নয়


247

একটি NumPy অ্যারে তৈরি করার পরে এবং এটি জ্যাঙ্গো প্রসঙ্গ ভেরিয়েবল হিসাবে সংরক্ষণ করার পরে, ওয়েবপৃষ্ঠাটি লোড করার সময় আমি নিম্নলিখিত ত্রুটিটি পেয়েছি:

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

এটার মানে কি?


19
এর অর্থ হ'ল কোথাও কোনও কিছু jsonমডিউলটি ব্যবহার করে একটি নমপি অ্যারে ফেলে দেওয়ার চেষ্টা করছে । তবে numpy.ndarrayএমন কোনও ধরণ নয় যা jsonকীভাবে পরিচালনা করতে পারে knows হয় আপনার নিজের সিরিয়ালাইজারটি লিখতে হবে, বা (আরও সহজভাবে) list(your_array)जेএসএস লিখছেন যা যা তা পাস করুন ।
মিগিলসন

24
নোট list(your_array)সবসময় কাজ করবে না কারণ এটি নেটিভ ইনটগুলি নয়, আর্দ্র কালি ফেরত দেয়। your_array.to_list()পরিবর্তে ব্যবহার করুন।
অশিশাল জাল

18
@ আশীষিংলের মন্তব্য সম্পর্কে একটি নোট, এটি আপনার_আরএ.টোলিস্ট () হওয়া উচিত, টু_লিস্ট () নয়।
Vega

উত্তর:


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
@ ফ্র্যাঙ্কলিওও আমি কারণটি খুঁজে পেয়েছি যে tolist()ডেটা বড় হলে প্রচুর পরিমাণ সময় লাগে।
হারভেট

4
@ নিখিলপ্রভু জেএসএন হ'ল জাভাস্ক্রিপ্ট অবজেক্ট নোটেশন, এবং তাই কেবল জাভাস্ক্রিপ্ট ভাষা থেকে মূল রচনাগুলি উপস্থাপন করতে পারে: অবজেক্টস (পাইথন ডিক্টের সাথে সমতুল্য), অ্যারে (অজগর তালিকার সাথে সাদৃশ্য), সংখ্যা, বুলিয়ান, স্ট্রিং এবং নালস (পাইথন ননের সাথে সাদৃশ্যপূর্ণ) )। নম্পি অ্যারে এই জিনিসগুলির মধ্যে কোনওটি নয় এবং তাই জেএসএনে সিরিয়ালাইজ করা যায় না। কিছু জেএসও -র মতো ফর্ম (তালিকার তালিকা) তে রূপান্তরিত হতে পারে, যা এই উত্তরটি দেয়।
ক্রিস এল বার্নস

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_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
এটি বোর্ডের উচ্চতর উপায়ে হওয়া উচিত, এটি এটি করার সাধারণ এবং সঠিকভাবে বিমূর্ত পদ্ধতি। ধন্যবাদ!
thclark

2
তালিকা থেকে ndarray ফিরে পেতে একটি সহজ উপায় আছে?
দার্কস্টিলপেনগুইন

5
@ দার্কস্টিলপেনগুইন আপনি কি খুঁজছেন numpy.asarray()?
আইওলাস

3
এই উত্তরটি দুর্দান্ত এবং সহজেই জাস্টসোন হিসাবে নম্পু ফ্লোট 32 এবং এনপি.ফ্লোয়াট 64 মানগুলিকে ক্রমিকায়িত করতে প্রসারিত হতে পারে: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
গ্রেট! এবং আমি 2 ডি এনপি.আরয়ের জন্য মনে করি এটির মতো কিছু হবে 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পিছনে পড়তে আপনি এটি ব্যবহার করতে পারেন: with open(path, 'r') as f: data = json.load(f)যা আপনার ডেটা সহ একটি অভিধান দেয়।
tsveti_iko

jsonফাইলটি পড়ার জন্য এবং তারপরে আউটপুটটি data = json.loads(data)
ডিসরিয়ালাইজ করার জন্য

বাইটস ডেটাটাইপ হ্যান্ডেল করতে আমাকে এটি যুক্ত করতে হয়েছিল .. ধরে নিচ্ছি সমস্ত বাইটগুলি utf-8 স্ট্রিং। এলিফ আইসনস্ট্যান্স (আপত্তি, (বাইটস,)): রিটার্ন আপত্তি.ডেকোড ("utf-8")
সোচি হায়াশি

+1 টি। আমাদের "ডিফল্ট ডিফল্ট (স্ব, আপত্তি)" এর শেষে "রিটার্ন জেএসন.জেএসএনইঙ্কোডার.ডিফফল (স্ব, আপত্তি)" লাইনটি কেন দরকার?
হ্যান্স

23

json.dumps defaultকোয়ার্গ ব্যবহার করুন :

ডিফল্ট এমন একটি ফাংশন হওয়া উচিত যা অবজেক্টের জন্য ডাকা হয় যা অন্যথায় সিরিয়ালাইজ করা যায় না।

ইন 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__: সেখানে লাইনের ভূমিকা কী ? উদাহরণস্বরূপ পরীক্ষা করা কি যথেষ্ট হবে না?
রামন মার্টিনেজ

@ র্যামনমার্টিনিজ, অবজেক্টটি একটি নোংরা বস্তু তা জানতে, এইভাবে আমি .itemপ্রায় যে কোনও অলস বস্তুর জন্য ব্যবহার করতে পারি । defaultক্রিয়াকলাপটি অজানা সমস্ত ধরণের json.dumpsক্রমিকায়িত করার চেষ্টা করা হয়। শুধু অদ্ভুত নয়
মোশেইভি

5

এটি ডিফল্ট দ্বারা সমর্থিত নয়, তবে আপনি এটি বেশ সহজেই কাজ করতে পারেন! আপনি যদি একই তথ্যটি আবার চান তবে আপনি এনকোড করতে চান এমন বেশ কয়েকটি জিনিস রয়েছে:

  • ডেটা নিজেই, যা আপনি obj.tolist()উল্লিখিত @ ট্র্যাভেলিংবোন হিসাবে পেতে পারেন । কখনও কখনও এটি যথেষ্ট ভাল হতে পারে।
  • ডেটা টাইপ। আমি মনে করি এটি বেশ কয়েকটি ক্ষেত্রে গুরুত্বপূর্ণ।
  • মাত্রা (অগত্যা 2 ডি নয়), যা উপরের থেকে উদ্ভূত হতে পারে যদি আপনি ধরে নেন যে ইনপুটটি সত্যই একটি 'আয়তক্ষেত্রাকার' গ্রিড।
  • মেমরি ক্রম (সারি- বা কলাম-প্রধান)। এটি প্রায়শই গুরুত্বপূর্ণ হয় না, তবে কখনও কখনও এটি হয় (যেমন পারফরম্যান্স), তবে কেন সবকিছু সংরক্ষণ করবেন না?

তদুপরি, আপনার অদ্ভুত অ্যারে আপনার ডেটা কাঠামোর অংশ হতে পারে, যেমন আপনার ভিতরে কিছু ম্যাট্রিক রয়েছে es এর জন্য আপনি একটি কাস্টম এনকোডার ব্যবহার করতে পারেন যা মূলত উপরেরটি করে।

সমাধান কার্যকর করার জন্য এটি যথেষ্ট হওয়া উচিত। অথবা আপনি জসন-ট্রিকস ব্যবহার করতে পারেন যা কেবল এটি করে (এবং অন্যান্য বিভিন্ন ধরণের সমর্থন করে) (অস্বীকৃতি: আমি এটি তৈরি করেছি)।

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

এছাড়াও পাইথন vs > পাইথন তালিকা বনাম অ্যারেতে তালিকা সম্পর্কিত বনাম অ্যারে সম্পর্কিত আরও কিছু আকর্ষণীয় তথ্য - কখন ব্যবহার করবেন?

এটি লক্ষ করা যায় যে একবার আমি আমার অ্যারেটিকে JSON ফাইলে সংরক্ষণের আগে এই তালিকায় এখনই যাইহোক, আমার নিয়োগের সময়ে রূপান্তরিত করেছি, একবার যদি আমি পরে ব্যবহারের জন্য জেএসওএন ফাইলটি পড়ে থাকি, তবে আমি এটি তালিকা ফর্মে ব্যবহার চালিয়ে যেতে পারি (যেমন এটিকে আবার অ্যারে রূপান্তর করার বিরোধিতা করে)।

এবং স্ক্রিনে আসলে (কমা বিচ্ছিন্ন) বনাম একটি অ্যারে (কম-বিচ্ছিন্ন নয়) এইভাবে পর্দায় ভাল দেখতে (আমার মতে) দেখতে সুন্দর লাগছে।

উপরের @ ট্র্যাভেলবোনস। টোলিস্ট () পদ্ধতিটি ব্যবহার করে, আমি এ জাতীয় ব্যবহার করছি (আমিও পেয়েছি এমন কয়েকটি ত্রুটি ধরা):

সংরক্ষণ করুন ডিকশনারি

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

প্রকারের ত্রুটি: অ্যারে ([[0.46872085, 0.67374235, 1.0218339, 0.13210179, 0.5440686, 0.9140083, 0.58720225, 0.2199381]], টাইপ = ফ্লোট 32) জেএসএন সিরিয়ালযোগ্য নয়

আমি যখন জসন ফর্ম্যাটে প্রতিক্রিয়া আশা করছিলাম তখন মডেল.প্রেডিক্ট () - এ ডেটা তালিকার তালিকা পাস করার চেষ্টা করার সময় উপরের বর্ণিত ত্রুটিটি নিক্ষিপ্ত হয়েছিল।

> 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 পূর্বাভাস = লোডড_মডেল.প্রেডিক্ট (ডি) দেখতে স্ক্রোল করে থাকেন যেখানে এই লাইন কোডটি অ্যারে ডেটাটাইপ টাইপের আউটপুট উত্পন্ন করছে, যখন আপনি অ্যারেটিকে জসন ফর্ম্যাটে রূপান্তর করার চেষ্টা করছেন এটি সম্ভব নয়

পরিশেষে আমি প্রাপ্ত কোডটিকে নিম্নলিখিত লাইন দ্বারা টাইপ তালিকায় রূপান্তর করে সমাধানটি পেয়েছি

পূর্বাভাস = loaded_model.predict (d)
listtype = পূর্বাভাস.টোলিস্ট () রিটার্ন jsonif (listtype)

ভুম! অবশেষে প্রত্যাশিত আউটপুট পেয়েছি, এখানে চিত্র বর্ণনা লিখুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.