【问题标题】:Mathematica dynamic to plot matrix dataMathematica 动态绘制矩阵数据
【发布时间】:2011-12-13 10:26:44
【问题描述】:

我正在尝试使用 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 代表氢,1475 代表 C8H14N+,Grain-),尽管该图有名称。

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

谢谢

【问题讨论】:

  • 20001 x 1476 实际上是一个相当温和的矩阵大小。您应该能够在内存中很好地解决这个问题,而无需依赖数据库。

标签: dynamic matrix wolfram-mathematica plot


【解决方案1】:

Mike 的建议不错,但如果您不想将其放入数据库中,请使用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]

要获得弹出菜单,请使用控制器规范的{i,listofvalues} 语法。

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

这在我的系统上运行得非常快。 (两岁的 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]

如果您只想逐步浏览图像,请单击滑块控制器旁边的小加号以获得更详细的控件。

【讨论】:

    【解决方案2】:

    要在 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}
     ]
    ]
    

    例如,对于

    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]
      ]
      

      【讨论】:

      • 为此使用数据库可能有点矫枉过正。他的矩阵只有大约 300 万个元素,即使在我 4 岁的笔记本电脑上,Mathematica 也能愉快地处理这些元素。不过,如果您有一个更大的数据集,尤其是如果它已经在数据库中,这是一个好主意。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-25
      • 1970-01-01
      • 2020-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多