16

This seems like it should be a simple question, but I am running into some difficulty in doing this with Mathematica. Right now, I have a list like this:

data1={0, 0, 0, 0, 0, 0, 3, 1, 10, 3, 11, 1, 0, 0, 32, 0, 1, 0, 5, 0, 2, 0, 25, 0, 1, 0, 1, 
       0, 0, 0, 0, 7, 0, 0, 0, 0, 13, 4, 0, 5, 0, 0, 2, 3, 4, 0, 0, 95, 4, 16, 11, 2, 0, 0, 
       81, 35, 0, 0, 0, 33, 0, 0, 0, 0, 0, 5, 42, 0, 0, 0};

I want to insert "1997" into the list after each element and transpose it, so that it will look like so: {{1997,0},{1997,0},{1997,0}...}. So far so good.

Unfortunately, the only way I know how to do this is to manually create a list of equal length to data1 (70 "1997"s in a row). I also do not know how to create a list that is just 70 "1997"s in a row. I've plumbed the documentation and tried every command I can think of, but the closest I can get are either functions or a list that resembles {{1997,0,1997,0,1997,0...} etc.

rm -rf
  • 88,781
  • 21
  • 293
  • 472
canadian_scholar
  • 3,754
  • 1
  • 27
  • 45
  • 5
    Ian, you have great talent for asking questions that have a thousand and one ways to do them. – rcollyer Apr 25 '12 at 22:32
  • 2
    There are several good solutions to your problem below, but as an aside about your question of how to generate a list, there are a couple of easy ways: ConstantArray[1997,70] or Table[1997,{70}]. – wxffles Apr 25 '12 at 22:49
  • 1
    @wxffles Thanks for this. It's too bad ConstantArray isn't in the "list manipulations" docs section, as it's a great command to have in one's list toolkit! – canadian_scholar Apr 25 '12 at 22:52
  • @rcollyer Indeed - making it so tricky to pick just one as the accepted answer... – canadian_scholar Apr 25 '12 at 22:52
  • Consider speed as the final arbiter. Most likely, then, it is Thread. – rcollyer Apr 25 '12 at 23:44
  • 4
    It seems I've found a pretty fast and simple method based on Tuples. This question is really good example for testing efficiency of various methods. – Artes Apr 26 '12 at 02:10
  • 2
    Ian, I find ConstantArray to verbose, for my tastes, though, I do use it. If I want something terse, I use Array[1997&, 70]. I doubt it is faster to execute, but it is a lot faster to type! However, Developer`PackedArrayQ[Array[...]] == False, while it is True for ConstantArray, implying a speed hit for Array. – rcollyer Apr 26 '12 at 02:49

5 Answers5

32

Absolutely unbeatable :

Tuples[{{1997}, data1}]

All other methods are much slower even Verbeia's {1997,#}&/@ data1 or dws' Thread[{1997, data1}]

Tuples[{{1997}, data1}] === ({1997, #} & /@ data1) ===  Thread[{1997, data1}]
True

We compare the most efficient methods for a long list :

 list = RandomChoice[data1, 10^7];

and results :

Thread[{1997, list}]; // AbsoluteTiming // First
{1997, #} & /@ list; // AbsoluteTiming // First
Tuples[{{1997}, list}]; // AbsoluteTiming // First
1.6000000
0.8470000
0.1960000

Other methods just for completeness:

Inner[List, Table[1997, {Length @ data1}], data1, List]

Outer[List, {1997}, data1] // Flatten[#, 1] &

Transpose@{Table[1997, {Length @ data1}], data1}
Artes
  • 57,212
  • 12
  • 157
  • 245
  • 2
    Apparently, we have a winner in Tuples. I've never used the second form, so I don't think of it. You already had my +1, but I'd give you another for that, if I could. – rcollyer Apr 26 '12 at 02:21
  • 1
    @rcollyer Thank You ! I knew there was a simple and fast method, however I couldn't find it and tried many strange ways until Tuples. – Artes Apr 26 '12 at 02:27
  • I understand about attempting to use strange ways to solve a problem. The binary tree method, as written, is 4 times slower than any other method. Even with the speed ups! :) – rcollyer Apr 26 '12 at 02:41
  • I haven't read yet carefully those "strange ways" but that seems interesting. – Artes Apr 26 '12 at 02:49
  • I highly recommend the method Leonid pointed to as it is compiled. The issue with Andy's requirements, though, is that they include $\pm\infty$ which cannot be compiled. – rcollyer Apr 26 '12 at 02:53
  • 2
    Nice work! For your "other methods" ConstantArray will be an order of magnitude faster than Table. – Mr.Wizard Apr 26 '12 at 04:57
  • @Mr.Wizard Thank You ! ConstantArray is a real improvement for "other methods", but since it is entangled with Transpose or Inner, there we get only roughly 10-15 % of speed-up with respect to Table. – Artes Apr 26 '12 at 09:16
26

Another possibility:

Thread[{1997,data1}]
dws
  • 801
  • 8
  • 9
14

The following works and is the way I would recommend:

{1997,#}&/@ data1

There is no need to create a list of 1997s of the same length as your original data.

I can think of a few other ways but they are more roundabout.

This version uses the optional third argument of Riffle.

Partition[Riffle[data1, 1997, {1, 2 Length[data1] - 1, 2}], 2]

There is no point using FoldList if you aren't using the intermediate values of the lists in your calculations, but the following works if what you really want is something more complicated than just joining 1997.

FoldList[{1997, #2} &, {1997, First[data1]}, Rest@data1]
Verbeia
  • 34,233
  • 9
  • 109
  • 224
7

As always, there are several ways to skin the cat. Here's yet another one:

data1 /. x_Integer :> {1997, x}

Use x_Real or x_?NumericQ as necessary, if your list is not exactly made of integers as in the example.

rm -rf
  • 88,781
  • 21
  • 293
  • 472
5

One more:

ArrayFlatten@{{1997, List /@ data1}}
Murta
  • 26,275
  • 6
  • 76
  • 166