Python >> Tutoriel Python >  >> Python Tag >> NumPy

Échanger des tableaux numpy entre Python et Mathematica ?

Vous pouvez utiliser le format binaire pour accélérer le processus :

côté python

import numpy as np
array = np.random.rand(100000000);
array.astype('float32').tofile('np.dat')

Côté Mathematica

data = 
   BinaryReadList["np.dat", "Real32"]; // AbsoluteTiming
(* {2.56679, Null} *)

data // Dimensions
(* {100000000} *)

Voici un modèle pour lire un fichier ".npy" binaire numpy créé simplement par

numpy.save(filename,array)

ce format de fichier a la structure de tableau encodée sous la forme d'une chaîne python que nous devons analyser..

{'descr': '<f8', 'fortran_order': False, 'shape': (3, 4, 5), }

l'ordre des octets est également encodé afin que ce format soit portable sur le matériel.

tout ce code analyse un petit en-tête et les données réelles lues sont un seul BinaryReadList donc ça devrait aller très vite..

getnpy[file_] := 
  Module[{a, f = OpenRead[file, BinaryFormat -> True], version, 
    headerlen, header, dims, type, typ, byto},
    a = If[
     BinaryRead[f, "Byte"] == 147 &&         
      BinaryReadList[f, "Character8", 5] == Characters["NUMPY"] ,
     version = BinaryReadList[f, "Byte", 2];
     headerlen = BinaryRead[f, "Integer16", ByteOrdering -> -1];
     header = [email protected][f, "Character8", headerlen];
     dims = StringCases[header,"'shape':" ~~ Whitespace ~~ "(" ~~ 
                 s : {NumberString, ",", Whitespace} .. ~~ ")" :> 
            ToExpression[
            "{" ~~
            If[StringTake[s, -1] == ",", StringDrop[s, -1], s] ~~ 
            "}"]][[1]];
     type = 
      StringCases[header, 
        "'descr':" ~~ Whitespace ~~ 
          Shortest["'" ~~ s : _ ... ~~ "'"] :> s][[1]];
     byto = 
      Switch[StringTake[type, 1], "<", -1, ">", 1, _, $ByteOrdering];
     If[MemberQ[{"<", ">","|","="}, StringTake[type, 1]], 
      type = StringDrop[type, 1]];
     typ = 
      Switch[ type ,
        "f8" , "Real64" ,
        "i8" , "Integer64" ,
          _  , Print["unknown type", header]; 0];
     If[typ != 0, 
      ArrayReshape[BinaryReadList[f, typ, ByteOrdering -> byto], 
       dims], 0 ], Print["not a npy"]; 0];
   Close[f]; a];

getnpy["test.npy"]

notez que je n'ai mis que quelques types que vous pourriez rencontrer dans le Switch . Voir le manuel sous BinaryRead si vous avez besoin d'en ajouter d'autres. De plus, je n'ai pas implémenté la clé 'fortran_order', supposons simplement que la valeur par défaut est false.