2012-11-19 74 views
3

我有一個numpy數組,我想與Json轉儲。該陣列是這樣的:轉儲與Json的2D Python數組

array([['foo', 'bar', 'something', ... 
     'more'], 
     ['0.4', '0.7', '0.83', ... 
     '0.3', '0.62', '0.51']] 

,我想使用JSON傾倒它在一個字符串如下:

foo: 0.4 
bar: 0.7 
something: 0.51 
... 

我曾嘗試用:

import jason 
my_string = json.dumps(my_array) 

但它抱怨着:

"not JSON serializable" 

任何想法如何轉儲此字符串與Json

更新:

請不是我關心的排序,行應該按以下順序打印:

array[0,0] : array[0,1] 
array[1,0] : array[1,1] 
array[2,0] : array[2,1] 
# etc ... 
+0

你的數組索引不正確。對於像這樣的二維數組,語法是'array [row] [column]',因爲你只有兩行,所以第一個索引的最大值將是'1'。 – martineau

回答

6

什麼對我有用 - 因爲擁有更大的1024x1002 float64陣列 - 被轉換爲base64。

def Base64Encode(ndarray): 
    return json.dumps([str(ndarray.dtype),base64.b64encode(ndarray),ndarray.shape]) 
def Base64Decode(jsonDump): 
    loaded = json.loads(jsonDump) 
    dtype = np.dtype(loaded[0]) 
    arr = np.frombuffer(base64.decodestring(loaded[1]),dtype) 
    if len(loaded) > 2: 
     return arr.reshape(loaded[2]) 
    return arr 

''' just to compare ''' 
def SimpleEncode(ndarray): 
    return json.dumps(ndarray.tolist()) 
def SimpleDecode(jsonDump): 
    return np.array(json.loads(jsonDump)) 

的IPython%timeit結果分得很清楚爲base64:

arr = np.random.random_sample((1000, 1000)) 

print 'Simple Convert' 
%timeit SimpleDecode(SimpleEncode(arr)) 
print 'Base64 Encoding' 
%timeit Base64Decode(Base64Encode(arr)) 

結果:末

Simple Convert 
1 loops, best of 3: 1.42 s per loop 
Base64 Encoding 
10 loops, best of 3: 171 ms per loop 
1

不知道的JSON序列化的一部分,但你可以將其轉換爲一個字典第一?這看起來像是JSON輸出的更自然的格式,並且會處理數據類型的任何問題。

my_dict = dict(zip(my_array[1], my_array[0]))

+0

這會保留我在數組中的順序嗎? (即行'my_array [0,0]:my_array [0,1]'應該在行my_array [1,0]:my_array [1,1]'之前打印,等等。 –

+0

但字典保留其鍵-values unsorted。如何保證我的字典中的條目按照正確的順序打印,當我將它傳遞給JSON時 –

+0

可能不是,所以也許這不起作用Python的dicts默認是無序的,我認爲Python 2.7有一個OrderedDict類,但是否能工作取決於你的JSON庫是否會尊重排序(剛注意到你回覆了我以前的評論,我刪除了它)。新來的,對不起。) –

0

如果所有的值都是數字,你總是可以做手工,如果一切都失敗了:

my_array = [['0.4', '0.7', '0.83', '0.3', '0.62', '0.51'], 
      ['foo', 'bar', 'something', 'more']] 

pairs = zip(my_array[1], my_array[0]) 
json_values = ('"{}": {}'.format(label, value) for label, value in pairs) 
my_string = '{' + ', '.join(json_values) + '}' 

print my_string # '{"foo": 0.4, "bar": 0.7, "something": 0.83, "more": 0.3}' 
0

如果你只是試圖讓你的陣列的一個漂亮的字符串表示,並使用一個字符串數組類型不會給你想要的表示,那麼消息序列化格式不是要使用的東西。序列化格式用於保存/傳輸數據。 Json很好,因爲它通常也是人類可讀的,但這不是目的,並且將其強制爲不同的格式將使其不再是json序列化。即使savetxt和loadtxt numpy選項也不適用於所需的格式(重複每列的第一行)。你可以讓自己的序列,如果有使用下面的代碼是在這種格式:

def prettySerialize(inArray): 
    ids = inArray[0] 
    strRep = '' 

    for row in inArray[1:]: 
     for i,item in enumerate(row): 
      rowStr = id[i] + ':' + item + '\n' 
      strRep += rowStr 

    return strRep 

這裏的問題是,這將是非常緩慢,並且該陣列的一個更大的表示(重複「ID 「一遍又一遍地重複)。我強烈推薦使用純json(或msgpack)解決方案,除非您專門爲人類閱讀格式化...

這是我用於使用msgpack(也可以與json一起使用)序列化的解決方案。 ..轉換成包括D型和排列形狀的元組:

def arrayToTuple(arr): 
    if arr is None: 
     return None 

    return (arr.dtype.str, arr.shape, arr.tostring()) 

def arrayFromTuple(tupl): 
    if tupl is None: 
     return None 

    typeStr, shape, dataStr = tupl 

    resultArray = numpy.fromstring(dataStr, dtype=typeStr).reshape(shape) 

    return resultArray 

所以轉儲和裝載命令是:

strRep = json.dumps(arrayToTuple(arr)) 
arrayFromTuple(json.loads(strRep)) 

,這也適用於msgpack.dumps和msgpack.loads(更快更緊湊二進制表示)。

可能適用於您的數組的一個警告:如果您的numpy數組是一個對象dtype,那麼它將不會以標準方法作爲完整數組序列化。您將不得不逐個序列化每個對象,因爲它存儲在數組中的對象標識而不是數據。使用dtype作爲dtype ='| S',其中最大字符串長度將使數組可序列化。