转换嵌套列表而不复制或丢失精度

hig*_*ggy 6 wolfram-mathematica

我正在使用Mathematica 7来处理大型数据集.数据集是有符号整数的三维数组.这三个级别可以被认为对应于每个镜头的X个点,每个扫描的Y个镜头和每个组的Z个扫描.

我还有一个"归零"镜头(包含X点,它是整数的符号分数),我想从数据集中的每个镜头中减去.之后,我将永远不再需要原始数据集.

如何在不创建数据集的新副本或部分数据集的情况下执行此转换?从概念上讲,数据集位于内存中,我想扫描每个元素,并在内存中的该位置进行更改,而不会将其永久复制到其他内存位置.

以下自包含代码捕获了我尝试执行的所有方面:

(* Create some offsetted data, and a zero data set. *)
myData = Table[Table[Table[RandomInteger[{1, 100}], {k, 500}], {j, 400}], {i, 200}];
myZero = Table[RandomInteger[{1, 9}]/RandomInteger[{1, 9}] + 50, {i, 500}];

(* Method 1 *)
myData = Table[
   f1 = myData[[i]];
   Table[
     f2 = f1[[j]];
     f2 - myZero, {j, 400}], {i, 200}];

(* Method 2 *)
Do[
 Do[
  myData[[i]][[j]] = myData[[i]][[j]] - myZero, {j, 400}], {i, 200}]

(* Method 3 *)
Attributes[Zeroing] = {HoldFirst};
Zeroing[x_] := Module[{}, 
   Do[
     Do[
       x[[i]][[j]] = x[[i]][[j]] - myZero, {j, Length[x[[1]]]}
       ], {i, Length[x]}
     ]
 ];
Run Code Online (Sandbox Code Playgroud)

(注意:帽子提示Aaron Honecker方法#3.)

在我的机器上(Intel Core2 Duo CPU 3.17 GHz,4 GB RAM,32位Windows 7),这三种方法都使用大约1.25 GB的内存,#2和#3整流罩稍好一些.

如果我不介意失去精度,缠绕N[ ]周围的内脏myDatamyZero正在被创建时,他们增加了他们通过150 MB内存最初的大小,但降低了内存归零所需的量(按方法#1以上#3) 1.25 GB低至300 MB!这是我的工作解决方案,但知道处理这个问题的最佳方法会很棒.

Sza*_*lcs 6

不幸的是我现在没有时间,所以我必须简明扼要......

处理大数据时,您需要注意Mathematica有一种称为压缩数组的不同存储格式,它比常规数据更紧凑,更快,但仅适用于机器实数或整数.

?Developer`*Packed*如果没有自动发生,请评估以查看可直接转换为/从哪些函数可用的函数.

因此,为什么我的解决方案快速且内存有效的简要解释是它使用打包数组.我测试使用Developer`PackedArrayQ我的数组永远不会解压缩,我使用机器实数(我应用于N[]所有)

In[1]:= myData = N@RandomInteger[{1, 100}, {200, 400, 500}];

In[2]:= myZero = 
  Developer`ToPackedArray@
   N@Table[RandomInteger[{1, 9}]/RandomInteger[{1, 9}] + 50, {i, 500}];

In[3]:= myData = Map[# - myZero &, myData, {2}]; // Timing

Out[3]= {1.516, Null}
Run Code Online (Sandbox Code Playgroud)

此外,您要求的操作("我想扫描每个元素,并在内存中的该位置更改它")称为映射(请参阅Map[]/@).