Mathematica动态绘制矩阵数据

5
我将尝试用Mathematica 7动态绘制矩阵中包含的数据。这些数据是通过化学模型获得的,存储格式如下。
[year  H    He     Li     C     ...  C8H14+,Grain- ]
[0     0    0.03   0.009  1E-3  ...  0             ]
[100   .1   0.03   0.009  1E-3  ...  0             ]
[200   .2   0.03   0.009  1E-3  ...  0             ]
[300   .2   0.03   0.009  1E-3  ...  0             ]
[...   ...  ...   ...     ...   ...  ...           ]
[1E6   .5   0.03   0.003  1E-8  ...  1E-25         ]

事实是,矩阵的维度为2001 * 1476(2000个步骤和第一行表示名称,1475种化合物+1列表示年份),非常大。

我正在尝试绘制任何一种化合物的浓度/年份图。这个已经做好了。

Manipulate[
  ListLogLogPlot[data[[All, {1, i}]], PlotLabel -> data[[1, i]] ], 
  {{i, 2, "Compound"}, 2, compounds, 1}
]

在这里,data是矩阵,compounds是变量,设置为模型化化合物的数量(此处为1475)。"compound"是滑块的标签。 问题在于,当浏览1400多个项目时,滑块移动得太快了,只需要几厘米的距离。 我尝试用下拉菜单来解决问题。

MenuView[
  Table[
    ListLogLogPlot[data[[All, {1, i}]],PlotLabel -> data[[1, i]]], {i, 2, compounds}
  ]
]

它也可以运行,但这是一个消耗处理器的过程(在执行16个内核的Xeon 16核服务器上需要10多分钟),因为Mathematica尝试在显示任何一个图之前绘制所有图。此外,下拉框没有名称,只有一系列数字(从氢的1到C8H14N +,Grain-的1475),即使图表有名称。

我正在寻找一种仅在需求时绘制图表并在下拉列表中显示名称(如果需要,默认情况下为H)的方法。或者我可以输入化合物名称的字段。这似乎可以通过 Dynamic [] 命令实现,但我无法使其正常工作。

谢谢


“20001 x 1476” 实际上是一个相当温和的矩阵大小。您应该能够在内存中轻松地处理它,而无需依赖数据库。 - Mike Bailey
3个回答

7

迈克的建议很好,但如果您不想把它放入数据库中,可以使用ContinuousAction->False选项。

testdata = 
  Join[{Table[ToString[series[i-1]], {i, 1475}]}, 
   RandomReal[{1., 100.}, {2000, 1476}]];

Manipulate[
 ListLogLogPlot[testdata[[All, {1, i}]], 
  PlotLabel -> testdata[[1, i]]], {{i, 2, "Compound"}, 2, 1475, 1}, 
 ContinuousAction -> False]

enter image description here

要获取弹出菜单,请使用{i,listofvalues}语法来指定控制器。

Manipulate[
 ListLogLogPlot[testdata[[All, {1, i}]], 
  PlotLabel -> testdata[[1, i]]], {i, Range[2, 1475]}, 
 ContinuousAction -> False]

enter image description here

这在我的电脑上运行得相当快。(一台两年的MacBook Pro)

一个更高级的版本:

spec = Thread[Range[2, 1476] -> Table[ToString[series[i]], {i, 1475}]];

Manipulate[
 ListLogLogPlot[testdata[[All, {1, i}]], 
  PlotLabel -> testdata[[1, i]]], {{i, 2, "Compound"}, spec}, 
 ContinuousAction -> False]

enter image description here

如果您只是想浏览图片,点击滑块控制器旁边的加号即可获得更详细的控制。

enter image description here


5

如果要在InputField中输入名称,您可以这样做:

compounds = Rest[data[[1]]];
Manipulate[
 If[MemberQ[compounds, compound], i = Position[compounds, compound][[1, 1]] + 1];
 ListLogLogPlot[data[[All, {1, i}]], PlotLabel -> data[[1, i]]],
 {{i, 2}, None},
 {{compound, data[[1, 2]], "Compound"}, InputField[#, String] &}]

这里,compounds 是所有化合物名称的列表。在 Manipulate 中,If 语句用于检查在 InputField 中输入的名称是否为有效的化合物。

其他人已经给出了创建一个大弹出式列表的方法。如果您不想浏览包含1475个化合物的弹出式列表,可以考虑将弹出式列表分成子列表。例如,这会将整个化合物列表分成每个包含 n=50 个元素的子列表,这可能会更容易导航。

compounds = Rest[data[[1]]];
With[{n = 50},
 Manipulate[
  i = 1 + Position[compounds, name][[1, 1]];
  ListLogLogPlot[data[[All, {1, i}]], PlotLabel -> data[[1, i]]],
  {{i, 2}, None},
  {{indexlist, 1, "Indices"},
   Table[i -> ToString[(i - 1) n + 1] <> " through " <> 
     ToString[Min[i n, Length[compounds]]], 
    {i, Ceiling[Length[compounds]/n]}], PopupMenu},
  {{name, compounds[[1]], "Compound"}, 
   compounds[[n (indexlist - 1) + 1 ;; 
      Min[Length[compounds], n indexlist]]], PopupMenu}
 ]
]

For example, for

data = Table[Join[{i}, RandomReal[{0, 1}, 1000]], {i, 1000}];
data = Join[{Prepend[Table["list " <> ToString[i], {i, 1000}], "year"]}, data];

这看起来像是弹出列表。

3

对于这样的数据集,建议将其全部存储在数据库中并使用DatabaseLink根据需要调用数据。然后将您的控制器(如弹出菜单)链接到SQLExecute代码或其他SQL函数。 类似以下片段的内容可以完成此任务:

DynamicModule[{x,data, ...},

Column[{

PopupMenu[Dynamic[x], {1 -> "category 1", 2 -> "category 2", 3 -> "category 3", ...}],

Dynamic[

data = SQLExecute[conn, "SELECT * FROM myDatabase.table WHERE my_id = `1`;", {x}];
ListLogLogPlot[data]
]

}]
]

实际上,您可能需要添加额外的弹出窗口并执行连接等操作。

编辑

不使用数据库但按要求使用输入字段的替代方案:

DynamicModule[{x = "He", rules, y},

 rules = Rule @@@ Transpose[{data[[1, All]], Range[Length[data[[1, All]]]]}];

 Column[{
   InputField[Dynamic[x], String],

   Dynamic[
    y = x /. rules;
    ListLogLogPlot[data[[All, {1, y}]], PlotLabel -> data[[1, y]]]
    ]

   }]
 ]

对于这样规模的规则列表,我想你可能会使用Dispatch。看看时间如何安排。看起来这是你正在运行的某种实验,所以我的首选仍然是将其转储到数据库中。

进一步编辑

如果您依赖输入字段,则需要插入条件语句,以便Mma只在y为整数时尝试绘图。

If[IntegerQ[y],
ListLogLogPlot,
Spacer[0]
]

1
对于这个问题,使用数据库可能有点过头了。他的矩阵只有大约3百万个元素,即使在我的4年老笔记本电脑上,Mathematica也可以轻松处理。但是,如果您有更大的数据集,特别是如果它已经在数据库中,那么这仍然是一个好主意。 - Mike Bailey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接