【问题标题】:Mathematica "AppendTo" function problemMathematica“AppendTo”函数问题
【发布时间】:2011-03-11 22:14:44
【问题描述】:

我是 Mathematica 的新手,在向数据表添加列时遇到了重大故障。我在 Vista 中运行 Mathematica 7。在这里问之前我花了很多时间RFD。

我有一个三列五行的数据表 (mydata)。我正在尝试向表中添加两个包含五个元素的列表(实际上是向数据表中添加两列)。

完美

Table[AppendTo[mydata[[i]],myfirstlist[[i]]],{i,4}] 

使用mydata // TableForm 打印出表格显示添加的列。

但是,当我尝试添加第二个列表时

Table[AppendTo[mydata[[i]],mysecondlist[[i]]],{i,5}]

要么 Mathematica 崩溃(!),要么我收到大量 Part::partwPart::spec 错误,说第 5 部分不存在。

但是,在所有错误消息之后(如果 Mathematica 没有崩溃),再次打印出数据表:mydata // TableForm 显示的数据表有五列,就像我想要的那样。修改后的数据表上的所有TableForm 格式选项都可以正常工作。

谁能告诉我我做错了什么?提前致谢!

【问题讨论】:

  • 您的意思是在第一次附加操作结束时使用{i,5} 而不是{i,4}? (我认为这与您的问题无关。)

标签: wolfram-mathematica


【解决方案1】:

让我们试着澄清一下双转置方法的组成。我对这种方法的独创性不做任何声明。我的重点是阐述的清晰。

让我们从 5 个列表开始。首先,我们将三个放在一张桌子上。然后我们将添加最后两个。

food = {"bagels", "lox", "cream cheese", "coffee", "blueberries"};
mammals = {"fisher cat", "weasel", "skunk", "raccon", "squirrel"};
painters = {"Picasso", "Rembrandt", "Klee", "Rousseau", "Warhol"};
countries = {"Brazil", "Portugal", "Azores", "Guinea Bissau", 
             "Cape Verde"};
sports = {"golf", "badminton", "football", "tennis", "rugby"};

前三个列表——食物、哺乳动物、画家——成为lists3 的元素。它们只是列表,但TableForm 在表格中将它们显示为

(lists3 = {food, mammals, painters}) // TableForm

mydata 将是 lists3 转置的名称。现在这三个列表显示为。这就是转置的作用:交换列和行。

(mydata = Transpose@lists3) // TableForm

这才是问题真正开始的地方。我们如何添加两个额外的列(即国家和体育的列表)?所以让我们处理剩下的两个列表。

(lists2 = {countries, sports}) // TableForm

所以我们可以加入Transpose[mydata]lists2....

(lists5 = Join[Transpose[mydata], lists2]) // TableForm

[或者,我们可能有Joined lists3lists2,因为第二个转置,mydata 的转置撤消了之前的转置。 lists3 只是mydata 的转置。 (反之亦然)。]

In[]:= lists3 === Transpose[mydata]
Out[]:= True

现在我们只需要Transpose的结果就可以得到想要的5个列表的最终表,每个列表占据自己的列:

Transpose@lists5 // TableForm

我希望这有助于阐明如何将两列添加到表中。我觉得这种方式相当清楚。您可能会发现其他更清晰的方法。

【讨论】:

  • @Mr.Wizard 我决定重新开始。并不是说我认为我的方法很新颖。我只是想找到一种清晰的方法来解释当我们通过双转置方法添加列时发生了什么。
  • @David +1 获取完整示例
  • @David +1 是的,转置是要走的路。
  • @belisarius 然而,它不一定是最快的。
  • @Mr.可能是,但对于初学者来说,这是做事的概念性方式。优化总是很棘手。
【解决方案2】:

这里有几件事要介绍。首先,下面的代码没有给我任何错误,所以这里可能还有其他事情发生。也许您应该发布一个产生错误的完整代码块。

mydata = Array[Subscript[{##}] &, {5, 3}];
myfirstlist = Range[1, 5];
mysecondlist = Range[6, 10];

Table[AppendTo[mydata[[i]], myfirstlist[[i]]], {i, 4}];
mydata // TableForm

Table[AppendTo[mydata[[i]], mysecondlist[[i]]], {i, 5}];
mydata // TableForm

其次,这里使用Table没有任何意义,因为你是直接修改mydataTable 会毫无意义地耗尽内存。

第三,有更好的方法来完成这项任务。

How to prepend a columnInserting into a 2d list

我必须收回我的明确声明,即有更好的方法。在将Table 更改为Do 并运行一些快速测试后,这对于某些数据来说似乎是一种具有竞争力的方法。

我使用的是 Mathematica 7,所以这似乎不是问题。

【讨论】:

  • 与上面的 Gareth 相同的评论:在这两种情况下我都应该跑到 5
  • @TomD 如果我阅读了那个帮助页面,我就会忘记它。我试图找到您链接的第一页,但找不到。
  • 好的,感谢所有回复的人。我也是堆栈溢出的新手,如果这不是回复的方式,请原谅我。我直接从 Mathematica“Appendto”文档中复制了代码。
  • 好的,感谢所有回复的人。我也是堆栈溢出的新手,如果这不是回复的方式,请原谅我。我直接从 Mathematica“Appendto”文档中复制了代码。 “应用程序”选项卡显示“将 m 指定为 2x2 矩阵:M={{a,b},{e,f}}。”然后“将一列添加到 m:”中 =col={x,y,z};表[AppendTo[m[[i]],col[[i]]],{i,3}]" Out={{a,b,x},{c,d,y},{e,f, z}}。”
【解决方案3】:

正如before 所提到的,有better alternatives 可以将列添加到列表中,就像GarethMr.Wizard,我似乎无法在第7 节重现该问题。但是,我希望专注于错误本身,看看我们是否可以通过这种方式纠正它。当 Mathematica 生成消息 Part::partw 时,它会吐出部分违规列表,例如

Range[1000][[1001]]
Part::partw: Part 1001 of  
    {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,
    31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,<<950>>} 
    does not exist.

所以,我要问的问题是哪个列表给我带来了问题?我最好的猜测是它是mysecondlist,我会检查Length @ mysecondlist,看看它实际上是否有 5 个元素。

【讨论】:

  • 我发现很多人容易混淆 {{1,2,3,4,5}} 或 {{1},{2},{3},{4},{5}}一个包含五个 Integer 元素的列表。也许这样的事情正在发生。
  • @belisarius,当然,这些信息很难阅读,尤其是当它们向你飞来的时候。希望他能采纳我的建议,仔细查看他的数据,甚至是消息本身。然而,崩溃也意味着发生了其他事情。
  • 我会检查长度。谢谢!
【解决方案4】:

好吧,这是我的两分钱,我认为这是一个非常快速且恕我直言最容易理解的结构。

首先,一些测试数组:

m = RandomInteger[100, {2000, 10000}];
l1 = RandomInteger[100, 2000];
l2 = RandomInteger[100, 2000];
{r, c} = Dimensions[m];

我稍微增加了测试阵列的大小以提高以下时序测量的准确性。

该方法涉及调用Part ([[...]])、AllSpan (;;) 的幂。

基本上,在添加两列后,我使用数据数组的未来维度设置了一个新的工作矩阵,然后使用AllSpan 添加原始矩阵,并仅使用All 添加其他列.然后我将废料矩阵复制回我们的原始矩阵,因为其他方法也返回修改后的数据矩阵。

n = ConstantArray[0, {r, c} + {0, 2}];
n[[All, 1 ;; c]] = m;
n[[All, c + 1]] = l1;
n[[All, c + 2]] = l2;
m = n;

关于时机:

Mean[
 Table[
  First[
   AbsoluteTiming[
    n2 = ConstantArray[0, {r, c} + {0, 2}];
    n2[[All, 1 ;; c]] = m;
    n2[[All, c + 1]] = l1;
    n2[[All, c + 2]] = l2;
    m2 = n2;
    ]
   ],
  {10}
  ]
 ]

0.1056061

(平均运行 10 次)

使用 Do 的另一种建议方法(Mr.Wizard 和 OP):

Mean[
 Table[
  n1 = m;
  First[
   AbsoluteTiming[
    Do[AppendTo[n1[[i]], l1[[i]]], {i, 2000}]; 
    Do[AppendTo[n1[[i]], l2[[i]]], {i, 2000}];
    ]
   ],
  {10}
  ]
 ]

0.4898280

结果是一样的:

In[9]:= n2 == n1

Out[9]= True

因此,一种概念上简单且快速(快 5 倍!)的方法。

【讨论】:

    【解决方案5】:

    我试图重现这个但失败了。我在 Windows XP 上运行 Mma 8;似乎差异并不重要,但谁知道呢?我说,先后,

    myData = {{1, 2, 3}, {2, 3, 4}, {8, 9, 10}, {1, 1, 1}, {2, 2, 2}}
    myFirstList = {9, 9, 9, 9, 9}
    mySecondList = {6, 6, 6, 6, 6}
    Table[AppendTo[myData[[i]], myFirstList[[i]]], {i, 4}]
    Table[AppendTo[myData[[i]], mySecondList[[i]]], {i, 5}]
    myData // TableForm
    

    并且得到 (0) 没有崩溃,(1) 没有错误或警告,以及 (2) 我期望的输出。 (注意:我在第一组追加的限制中使用了 4 而不是 5,就像在您的问题中一样,以防万一这会引起麻烦。)

    Mma 文档声称AppendTo[a,b] 始终等同于a=Append[a,b],这表明它没有就地修改列表。但我想知道 AppendTo 是否有时 确实 在认为这样做是安全的时候会修改列表;然后,如果它认为它是安全的而它不是,那么可能会产生令人讨厌的后果。如果将AppendTo 替换为Append + 普通赋值,是否还会发生奇怪的错误消息和崩溃?

    【讨论】:

    • 你的代码和我的一模一样,只是我的数据是实数,比如 30.45。我会按照你的建议尝试附加。感谢回复!
    猜你喜欢
    • 2014-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-23
    • 1970-01-01
    相关资源
    最近更新 更多