Lecture 4: Lists.

Lists

In most scientific calculations one handles large data sets. For example, you might have to calculate the pressure for a given molar volume and twenty different temperatures. Or you might want the pressure for all combinations of ten molar volumes and ten temperatures. You could give each one of the twenty temperatures a name and then give a name to each of the twenty pressures you have calculated. This would be tedious and prone to error. Mathematica uses the object called List to collect all the data on temperature or on pressures under one name.  In this Lecture you will learn 
	how to make Lists;
	how to extract elements from a list;
	how to add to a list;
	how to manipulate the structure of a list;
	how to make tables with lists;
	how to apply functions to lists;

Cell 1: The definition of a List and the kind of lists possible

Let us say that you want to evaluate a function for several temperatures, T=100, 200, ... 1000.  You can collect all the temperatures under one name by using the following syntax:

T={100,200,300,400,500,600,700,800,900,1000} (*Kelvin*)

This object is a list assigned to the symbol T.  Curly brackets (braces) can only be used to define a list and should not be used in any other expression.

The head of T is List

T//Head

The FullForm of a list is:

T//FullForm

The expressions between the commas inside the list (or in the argument of the function List) are called the elements of the list

Any valid Mathematica expression can be an element in a list.  Here is an example

li={a, x y^2, Cos,3.4}

The above is a valid list. I don't know what you might use if for, but the syntax is valid.

In particular the elements of a list could themselves be lists. For example

doubleList={{a,b},{1,2,3,4}}

This is a valid list that happens to have two elements which are themselves lists. The next one is also valid:

li={{a,b,c},c,{{A,B},{1,2,{E,F,{m,n}}}}}

Cell 2: How to extract elements of a list or an expression: the function Part.

It is a fine thing to collect all the temperatures under one name, as we did when we created the temperature list T defined in the previous cell. But sometimes I need to extract one element of the list, or several of them. The function Part helps us do this.

I want to extract the third element of the following list

T={100,200,300,400,500,600,700,800,900,1000}

The function Part does it.

Part[T,3]

The shorthand notation for this is

T[[3]]

I can use the extracted part in a any calculation.  For example, if I want to use the ideal gas law
	p= R T/v 
 to calculate the pressure for the third temperature in the list and the molar volume v=20 liter/mol, I can use (the value of R is R=0.082 liter atm/mol K)

0.082 T[[3]]/20

Or I can do

0.082 x/20/.x->T[[3]]

I can extract several members of the list. For example, let's make a list with the third and the fifth temperature in the list T.

Part[T,{3,5}]

The list T has a very simple structure. What do I do if the list is complicated, like the one given below

comp={1,2,3,{a,b,c},4,{d,{A,B,C},e,f}}

I can see the structure of the list comp by using the function TreeForm

comp//TreeForm

Note that the list has three levels: on the first level I have integers, on the second level I have low case letters and on the third level I have capital letters.

I'll look first at various parts:

comp
comp[[1]]

comp
comp[[2]]

comp
comp[[3]]

So far not very interesting. I get the first three elements of the list. Now the fun begins.

comp[[4]]

This is as it should be. The list {a,b,c} is one object and it is the fourth element

comp[[5]]

comp[[6]]

The list {d,{A,B,C},e,f} is one object and it is the sixth element.

comp[[7]]

Length[comp]

The list comp does not have a seventh element, the machine is mad at us for this absurd request, and lets us know what it thinks of us.

Part has given us the results above because we have interrogated only the first level of the list. Here is how you get to the second level

comp
comp[[4]]
comp[[4,1]]

I used the first line to remind you what the fourth element is. The second line has the meat. {a,b,c} is the fourth element and comp[[4,1]] is the first element of {a,b,c}. The syntax comp[[4,1]] has penetrated in the second level of the list. Here is more:

comp[[4,2]]

comp[[4,3]]

comp[[4,4]]

Ooops! Now let us try to penetrate deeper into the list:

comp={1,2,3,{a,b,c},4,{d,{A,B,C},e,f}}
comp[[6]]

comp[[6,2]]

comp[[6,2,2]]

You see how this works. Write yourself several complicated lists and extract their parts.

You will use Part fairly often. Here are several ways of using it:

You can assign a different value to one of the elements:

T
T[[3]]=1

T

You can apply a function to an element of  a list. 
First I define two functions, f and g.

Clear[f,g]
g[x_]:=x^2 Sin[x]
f[x_,y_,z_]:=x^2+y^2+z^2

Here is how you use them to act on the elements of a list

comp={1,2,3,{a,b,c},4,{d,{A,B,C},e,f}}
g[comp[[3]]]

f[comp[[4]]]

comp[[4]]
f[Sequence@@comp[[4]]]

You have encountered Sequence before. Sequence@@{a,b,c} turns the list {a, b, c} into the sequence a, b, c. If I don't use Sequence I get

f[comp[[4]]]

This function does not exist. We defined f to have three arguments. In the expression above, f is given one argument and f with one argument has not been defined.

Let us now act with the function f on the three argument in the inner list {A, B, C}:

comp

f@@comp[[6,2]]

f[T[[5]]]

Part applies not only to lists but to any expression. Here are a few examples

Create the expression w:

Clear[w]
w=3 x (Sin[y]^2 +Cos[y]^2)

Look at its TreeForm

w//TreeForm

This expression has many levels

w
{w[[1]],w[[2]],w[[3]]}

We can pick up the parts of the third part (which is ((Cos[y])^2) + ((Sin[x])^2))

w
w[[3,1]]

w
w[[3,2]]

We can go deeper into the third part:

w
w[[3,1,1]]

w
w[[3,1,1,1]]

You see how this goes.  
 There are an infinite number of ways of using this, once you start doing symbolic manipulations with mathematica.  For this particular expression you may have noticed that 
	((Cos[y])^2)+((Sin[y])^2)
is contained in w and the machine does not know that this is equal to one.  Let's replace ((Cos[y])^2)+((Sin[y])^2) with 1 in the expression w. I remind you below what w is and that the third part of w is ((Cos[y])^2)+((Sin[y])^2)

w
w[[3]]

Let's set the third part equal to 1.

w
w[[3]]
w[[3]]=1

Now the expression w is changed (((Cos[y])^2)+((Sin[y])^2) was replaced by 1):

w

Cell 3:How to extract elements of a list or an expression:the function Position.

The function Position has the syntax

	Position[expression1, expression2]
	
This assumes that expression2 is a part of expression1 and will find its position (in expression1).   I will show you how to use this for lists.

As you can see below, the third element of list T is 1. We can use Position to find out what is the position of 1 in the list T.

T
Position[T,1]

This tells me that 1 is the third element of the list T.  Wolfram has chosen to give the output of Position as a list of a list  (e.g. {{3}} instead of {3} or 3.

Here is what happens if I want to use this result to extract 1 from the list T (I use Position to find the position of 1 in T)

T

Part[T,Position[T,1]]

Let's remove one of the curly brackets

Position[T,1]//Flatten

Part[T,Position[T,1]//Flatten]

This extracts 1 from T but it places it in a List. Sometimes I want this, sometimes I would like to get the number 1 as output. Here is how we force Mathematica to do that:

f[Sequence@@(Position[T,1]//Flatten)]

T
Part[T,Sequence@@(Position[T,1]//Flatten)]

For example, here is what I do if I want to replace 1 in the list T with 300:

Part[T,Sequence@@(Position[T,1]//Flatten)]=300

Let us look now at the list T:

T

As you can see, 1 was replaced with 300, as intended.

Let us use Part and Position to manipulate a more complicated list (comp defined below)

comp={1,2,3,{a,b,c},4,{d,{A,B,C},e,f}}

Let's say that you know that the computer will create a list containing {A,B,C} as an element and that you want to change that element with R. Here is how you do that:
	first you find the position of {A,B,C} in the list comp:

Position[comp,{A,B,C}]

You want to use this information in Part in the form 
	Part[comp,6,2]
You got to turn {{6,2}} into 6,2 in the argument of the function Part. First you Flatten the double list:

Position[comp,{A,B,C}]//Flatten

Next you use Sequence@@ inside Part to turn {6,2} into 6,2

Part[comp,Sequence@@(Position[comp,{A,B,C}]//Flatten)]

Next you reassign the value of the part {A,B,C} by:

comp
Part[comp,Sequence@@(Position[comp,{A,B,C}]//Flatten)]=R

Now comp is:

comp

Position acts on any expression not just a List

w=a^2 Sin[x]+Sqrt[Cos[x]]
Position[w,Cos[x]]

What follows is wrong:

Part[w,Position[w,Cos[x]]]

Next is also wrong

Part[w,Position[w,Cos[x]]//Flatten]

Part[w,{1,1}]

This is right

Part[w,1,1]

Part[w,Sequence@@(Position[w,Cos[x]]//Flatten)]

Here is how you replace Cos[x] with Log[x]

Part[w,Sequence@@(Position[w,Cos[x]]//Flatten)]=Log[x]

w

Exercises:  
1. Part and Position act on any expression in the same way they act on lists. Play around: create some expressions and change them by using Part and Position. 
2. You have the list 
	{a, b, {2, 5,{A, B}}}
    Write an program that calculates
    	(A^2) Log[B]
    Pretend that you do not know where {A,B} is located in the list (this happens if you have an automated program that is written to handle any kind of list that contains a part {A,B})
3. You have the expression 
	(a^2) + Exp[Log[3 (x^2)]]
    Mathematica has not been instructed that Exp[Log[y]]=y. Write  a program that finds where Exp[Log[3 (x^2)]] is located and changes it to 3 (x^(2 ))to produce the expression 
    	(a^2)=3 (x^2)

Cell 3: Ways of generating  lists: Table

Table is a useful function that allows us to generate Lists.

Here is how you make a list of temperatures, that starts with 100 and ends with 1000, in increments of 50

Table[T,{T,100,1000,50}]

The syntax is 

	Table[expressionContainingT,{T, min, max, incr}]
	
T is the quantity being varied by Table. It will take values from min to max in increments incr. In the statement in the cell above, T varies from 100 to 1000 in increments of 50. Here are other uses. You can make a list containing the values of Cos

Table[Cos[x],{x,0,Pi,0.1}]

If you want to know the argument explicitly you can use

Table[{x,Cos[x]},{x,0,Pi,0.1}]

This list can be plotted by using the function  ListPlot

ListPlot[Table[{x,Cos[x]},{x,0,Pi,0.1}],
PlotStyle->PointSize[0.02], AxesLabel->{"x","cos[x]"}]

We will study ListPlot thoroughly in the Lecture on graphics. Here I note that 

	PlotStyle->PointSize[0.02]
	
makes the dots in the plot bigger than the default ones and 

	AxesLabel-> {"x","cos[x]"}
	
places x at the end of abscissa axis and cos[x] at the upper end of the ordinate axis.

You can create a more complex list by using a double iterator in Table:

Clear[f]
Table[f[i,j],{i,1,3},{j,1,3}]

There are two iterators in this expression: the first one is {i, 1, 3} and the second one is {j,1,3}. Table sets first i=1 and varies j=1, 2, 3 and makes a list with the results. This is the first list in the output. (i.e. {f[1,1], f[1,2], f[1,3]}). Then, it increases i to 2 and varies j through 1, 2 and 3 and makes a new lists with these results, etc.

It is easier to see the structure of the output list if we use the function TableForm

Table[f[i,j],{i,1,3},{j,1,3}]//TableForm

TableForm places the first list as the first row in the output, the second list as the second row, etc.

The second iterator can depend on the first iterator:

Clear[f]
Table[f[i,j],{i,1,3},{j,i,3}]

Display this with TableForm:

Table[f[i,j],{i,1,3},{j,i,3}]//TableForm

The first iterator makes i=1 and varies j from i=1 to 2 and 3. Then,  i is made 2 and the second iterator varies j from 2 to 3 etc.

Obviously the function TableForm is very useful for displaying data and the results of various calculations. You are going to learn more about it soon

Table can be used in calculations of various functions. I will calculate the pressure given by  the van der Waals equation
	p=((RT )/(v-b))-(a/(v^2))
	
for a variety of temperatures T and a given molar volume v. 
Below I define the function that gives the pressure of nitrogen (a=1.408 (liter^2)/bar, b=0.03183 liter/mol)

Clear[p]
p[T_,v_]:=Module[{R=0.0831 (*liter bar / K mol*),
               a=1.408 (*(liter^2)/bar*),
               b=0.03183 (*liter/mol*)},
R T/(v-b)-a/v^2  (*bar*)]

Let's check that the function works:

Clear[T,v]
p[T,v]

Here is how I can calculate the pressures (in bar) for a variety of temperatures and a molar volume v=22.4 liter, by using Table

pressure=Table[p[T,22.4], {T,200,1000,50}]

In the list produced above don't have a record of the temperature at which the pressure was calculated. If I want to have one, I do this:

pT=Table[{T,p[T,22.4]}, {T,200,1000,100}]

If I want to calculate the pressure at a variety of temperatures and molar volumes I can use Table with a double iterator:

results=Table[{T,v, p[T,v]},{T,200,1000,200},{v,10,20,2}]

To make a table I use TableForm.

results//TableForm

This is a bit strange: you have to read this vertically. The first three numbers in the first column are the temperature of 200, the volume of 10 liter/mol and the corresponding pressure of 1.65323 atm.

I can rearrange the list results to give me a more readable table:

results//Flatten[#,1]&//TableForm

You will study later this kind of manipulation. For now I only show you the effect of Flatten

results
results//Flatten[#,1]&

The list generated in this way if displays more nicely by TableForm

Cell 4: Acting with functions on the elements of lists: Map

You have learned quite a bit about Map in Lecture 3. 
The syntax is 
	Map[function, list]
or the short hand
	function/@list
Here are a few generic examples of what can be done with Map

Off[Remove::rmnsm]
Remove["Global`*"]

Map can apply a function f with one argument, to each element of a list:

f/@{a,b,c}

Map can act with a nameless function (here #^3&) on each element of a list:

#^3&/@{a,b,c}

Map can apply a function f having two arguments to each element of a list, by turning it into the nameless function f[#,3]& with one argument (the other argument has the fixed value 3)

f[#1,3]&/@{a,b,c}

Map can be used in a chain of several operations as in :
	Plus@@(#^3&/@{a,b,c,d})
 (/@) maps  a nameless function ( #^3& ) onto each element of the list {a,b,c}.  (this is done by (#^3&/@{a,b,c} ).  Plus@@  adds the elements of the resulting list

Plus@@(#^3&/@{a,b,c,d})

Exercise: use the same type of syntax to produce the expression a^2 b^2 c^2 d^2.

You can use Map in conjunction with Sequence to apply a function of two variable to a list of the form 
	{{a,b},{A,B},{1,2}}
to obtain 
	{f[a,b],f[A,B],f[1,2]}
If I apply Map directly I do not get the desired result:

I define the function f:

Clear[f]
f[x_,y_]:=3 x^2 Sin[2 y]+Log[Sin[x] Cos[y]]

If I use Map I do not get the desired result:

f/@{{a,b},{A,B},{1,2}}

The function f has two variables. The above statement used f with one argument (which is a list). No such function has been defined in this program. Here is how you do this right:

f[Sequence@@#]&/@{{a,b},{A,B},{1,2}}

The function Sequence applied to the list {a, b} turns it into a, b. See that below

Clear[g]
g[Sequence@@{a,b}]

Here are a more examples:

Clear[g]
g[x_,y_]:=x^2 y +Cos[x y]
g[Sequence@@#]&/@{{a,b},{A,B},{1,2}}

Let us calculate the pressure according to the van der Waals equation 

	p=(RT/((v-b)))-(a/(v^2))
	
for pairs of values of temperature and molar volume.
The data is 

	{{300, 20}, {400, 15}, {500, 10}}
	
The first element in the interior lists is the temperature (e.g. 300, 400,..) and the second is the molar volume (e.g. 20, 15,....)

p[T_,v_]:=Module[{R=0.0831 (*liter bar / K mol*),
               a=1.408 (*(liter^2)/bar*),
               b=0.03183 (*liter/mol*)},
R T/(v-b)-a/v^2  (*bar*)]
pressure=p[Sequence@@#]&/@{{300,20},{400,15},{500,10}}

The result is a list of the pressures corresponding to the temperatures and the volumes in {{300,20}, {400,15}, {500,10}}. It would be nice if the output list also has in it the temperature and the molar volumes the calculated pressures correspond to. We can arrange to include this information in, as you see below

{Sequence@@#,p[Sequence@@#]}&/@{{300,20},{400,15},{500,10}}

Now we can make a table with the results:

{Sequence@@#,p[Sequence@@#]}&/@{{300,20},{400,15},{500,10}}//TableForm

Here is something new about the Map: we can be a bit more specific about the position in the list on which f  acts, by using the levels of the list
	The syntax helping us do that is
		Map[function, list, level]
The third argument is the novelty here. To understand how this works we need to review the concept of level.
The structure of a list can be seen by using the function TreeForm:

{{a,b,c,{A,B}},1,2}//TreeForm

1,2 are elements at the first level
a,b,c are at the second level
A,B are at the third level

Map[f,list] acts at the first level, by default

Map[f,{{a,b,c,{A,B}},1,2}]

You can see this by specifically asking Map to act on the first level (see below;  1 says "act on the first level only")

Map[f,{{a,b,c,{A,B}},1,2},1]

You get the same result as when there was no 1 in the Map function

You can act on the first and the second levels by using the expression shown below

{{a,b,c,{A,B}},1,2}//TreeForm
Map[f,{{a,b,c,{A,B}},1,2},2]

As you can see this applies the function f to all elements on the first and second level

If you want to act on the second level only do this:

{{a,b,c,{A,B}},1,2}//TreeForm
Map[f,{{a,b,c,{A,B}},1,2},{2}]

As you can see above the elements 1 and 2 are in the first level and they were not acted upon. The list {A,B} is on the second level, but its elements A and B are on the third. Therefore the function acts on the whole list {A,B}, not on each element A and B. If you want to act on A and B you must map at the third level:

Map[f,{{a,b,c,{A,B}},1,2},{3}]

Here is a simple example of how this can be used. Let's say that you have calculated some physical quantities and your output is the following list:

li={2.343791034601,5.30417438293,{8.42849472691, 7.2502498264,{5.45207402,4.233546}}}

You want to display the output but the data you have is accurate to two decimal points and you feel silly giving output with five decimals. You can cut down the number of decimals with the function NumberForm:

NumberForm[23.3729304316,4]

NumberForm does not act if the argument is a list:

NumberForm[li]

Now display the TreeForm and use Map to force NumberForm[#,3]& to act on all elements down to the third level, inclusively.

li//TreeForm
Map[NumberForm[#,3]&,li,3]

You acted on all numbers in the list because you told Map to apply the function at first, second, and third level.

The syntax for NumberForm is 
	NumberForm[number, 3]
This keeps only three digits in number.
Since NumberForm is a function of two variables I use the nameless function 
	NumberForm[#,3]& 
in the Map function

Here are some more examples of using Map:

Map[f,{{a,b}, {A,B}} ]

Map[f,{{a,b}, {A,B}},2 ]

Map[f,{{a,b}, {A,B}},{2} ]

Map can be applies not only to lists but to expressions as well

z^2+2 a Cos[Sqrt[x^3]*(a+b)^2]//TreeForm

z^2+2 a Cos[Sqrt[x^3]*(a+b)^2]//FullForm

Clear[f]
f/@(z^2+2 a Cos[Sqrt[x^3]*(a+b)^2])

The above applied f to all the elements in the first level of the expression.

Here is another one:

(z^2+2 a Cos[Sqrt[x^3]*(a+b)^2])//Map[f,#,2]&

In the above I used the postfix form of the function and I made Map a nameless function of one variable 
Map[#,2]&. This is equivalent to

Map[f,(z^2+2 a Cos[Sqrt[x^3]*(a+b)^2]),2]

Now apply f to second level only

(z^2+2 a Cos[Sqrt[x^3]*(a+b)^2])//Map[f,#,{2}]&

Below I act at the third level only:

(z^2+2 a Cos[Sqrt[x^3]*(a+b)^2])//Map[f,#,{3}]&

Here is how you might use this. You have the expression 

	z^2+2 a Cos[Sqrt[x^3]*(a+b)^2]
	
and you want to expand (a+b)^2 in this expression to a^2 +2 a b +b^2.  
The function Expand will do the expansion for you:

(a+b)^2//Expand

The problem is: how to expand (a+b)^2 inside the expression z^2+2 a Cos[Sqrt[x^3]*(a+b)^2]. I  can Map the function expand at that position. Luckily (a+b)^2 is at the third level:

z^2+2 a Cos[Sqrt[x^3]*(a+b)^2]
z^2+2 a Cos[Sqrt[x^3]*(a+b)^2]//Map[Expand,#,{3}]&

Cell 5: Acting with functions on the elements of lists and expressions:  MapAt and Position

There is a much more precise function MapAt, which is to Map what surgery is to butchery. MapAt allows us to specify exactly the part (or the parts) of the list (or expression) on which we want to act with a function. Lets start with a complicated list:

comp={1,2,3,{a,b},{4, {d,e,{A,B,C},g}}}

comp//TreeForm

I assume that I have a function f and I want to act with it on comp to get

	{1,2,3,{a,b},{4,{d,e, {f[A], B,C},g}}}. 
	
Map will not help, as you can see below.

Map[f,comp,{4}]

I acted at the fourth level in the list but the function acts on A, and on B and on C. This is not what I want. 
I really want to get 

	{1,2,3,{a,b},{4,{d,e, {f[A], B,C},g}}}.
	
For this I have to use the function MapAt

Let us start with a study of MapAt by using it to accomplish a more modest task. I have the list

	simpl={a,b,c}
	
and I want to create the list

	{a,f[b],c}
	
Map cannot do that since a, b, and c are all on the same level in the list. Map will act with f on all the elements of the list. MapAt does what I want.

Clear[a,b,c,f]
simpl={a,b,c} 
Map[f,simpl]
MapAt[f,simpl,{2}]

MapAt has the following syntax

	MapAt[aFunction, AList, OneOrMorePositionsInTheList]

If you want you to act on two elements, the second and the third, you do:

MapAt[f,simpl,{{2},{3}}]

The third argument in MapAt is the position of the part on which I want to act with the function. Because of this MapAt is often used with the function Position. We have encountered Position already, but we barely skimmed the surface. Here is a bit more about Position
	Let us say that you know that your program will produce a list which contains the symbol Cos[x] and you want to apply the function ArcCos to it.  Here is how you do that:

The list is licos:

licos={a,{b,c},Cos[x],{d,Cos[y]^2}}

To apply MapAt I need to know the position of Cos in the list licos. If you are doing a simple calculation you can look at the list and determine the position. In licos, Cos is in the third position and in position 4,2,1 (run licos//TreeForm and you'll see why I say that. You can also use Part[licos, 4,2,1] to check whether I am right). However, if you write a larger program and you want it to run from the beginning to the end without your supervision, then you need to find the position of Cos automatically. The function Position will do that for you:

licos//TreeForm
po=Position[licos,Cos[_]]

Position is a very sophisticated function. In the syntax
	Position[list, pattern]
the second argument is a Pattern. In our example the pattern is Cos[ _ ]. I hope that you remember the underscore. It says to the computer: I want you to look for Cos[something] regardless of what something is. Identify where the Cos is in the list and tell me its position.

We can check that the results given by the function Position are right

{licos[[3]],licos[[4,2,1]]}

Exercise: explain the syntax in the following line and explain how the program works:

(Part[licos,Sequence@@#]&)/@Position[licos,Cos[_]]

Now let us use the combination of Position and MapAt to apply a function f to Cos[something] that is present in licos

po=Position[licos,Cos[_]]
MapAt[f,licos,po]

I can chain these statements and do the calculation in one line

MapAt[f,licos,Position[licos,Cos[_]]]

Here is another example of an one-liner:

li1={a,b,{Cos[Log[x]],3},5};
MapAt[f,li1,Position[li1,Cos[_]] ]

Another example is:

li2={a,Cos[x^2],{d,Cos[y^3]}};
MapAt[f,li2,Position[li2,Cos[_]]]

The expressions given above work for any function. In particular they work for the function ArcCos

MapAt[ArcCos,licos,Position[licos,Cos[_]]]

This expression works as intended. However I discover that Mathematica does not have the expression
	ArcCos[Cos[x]]=x
among its evaluation rules. No harm done. I can teach it to use this rule as you see below

%/.ArcCos[Cos[x_]]->x

The Rule I use ( after /. ) instructs the machine to look in the previous expression (the symbol % means the expression in the latest output), find 

	ArcCos[Cos[something]]
	 
and replace it with 

	something.
	
It does not matter what something is (this is why I use x_ in the expression ArcCos[Cos[x_]]

Another way of doing this in one line is to assign the list to the symbol li3, by using li3={a,b,{Cos[Log[x]],3},5} in the argument of MapAt (as done below). The machine evaluates the arguments in the order they appear in the function MapAt[arg1,arg2,arg3]; arg1 is evaluated first, arg2 next. When the evaluation of arg2 takes place the list is assigned the symbol li3 (the second argument is  li3={a,b,{Cos[Log[x]],3},5}) . Then, the machine evaluates the third argument and by then it knows that li3 is {a,b,{Cos[Log[x]],3},5}and uses that information

MapAt[f,li3={a,b,{Cos[Log[x]],3},5},Position[li3,Cos[_]] ]

How can you act with f only on Cos[x^2] but not on Cos[x^3]?  Pattern matching allows us to do that:
First find the position of Cos[y]^3 in the list

Position[{a,Cos[x^2],{d,Cos[y^3]}},Cos[_^3]]

For this I used the pattern Cos[_^3] which tells the machine:  look inside the list {a,Cos[x^2],{d,Cos[y^3]}} for Cos[something^3] and, regardless of what something is, give me the position of Cos[something^3] in the list.   Now that I know the position, I can act with f on the Cos[y^3] as you see below

MapAt[f,li2={a,li2=Cos[x^2],{d,Cos[y^3]}},Position[li2,Cos[_^3]]]

Now let us get back to the example that started all these:  I want to act with a function f on the element A in the sublist {A, B, C} of the list 

	{1,2,3,{a,b},{4,{d,e, {A,B,C},g}}}
	
to get

	{1,2,3,{a,b},{4,{d,e,{f[A],B,C},g}}}.

The list is:

comp

This is now very easy to do

MapAt[f,comp,Position[comp,A]]

Here is a more complicated example: act with f  on the list comp
	comp={1,2,3,{a,b},{4,{d,e,{A,B,C},g}}}
and turn it into 
	{1,2,3,{a,b},{4,{d,e,f[A,B,C] ,g}}}

First I need to find the position of the list {A, B, C}. This happens to be easily done by pattern matching because {A, B, C} is the only sublist with three elements

Position[comp,{_,_,_}]

In the list comp only{A, B, C} matches the pattern
	{_,_,_}

I can check that the position given above is the correct one (explain the syntax below)

Part[comp,Sequence@@(Position[comp,{_,_,_}]//Flatten)]

Now I can use MapAt to act with f on this position:

MapAt[f,comp,Position[comp,{_,_,_}]]

This almost does it but not quite. I want f[A,B,C] not f[{A, B, C}]. I have to use Sequence as follows:

MapAt[f[Sequence@@#]&,comp,Position[comp,{_,_,_}]]

MapAt and Position can be used with expressions, in the same way we used them for lists.

Let us say that you have performed symbolic manipulations and have arrived at the expression

	a x^2 +3 (Cos[y]^2+Sin[y]^2)^(1/2)
	
The machine has not been told by its maker that 

	Cos[y]^2 +Sin[y]^2 =1
	
But you know it and you want to simplify the expression. One way of doing this is to create the function 
f[x]=1 and use MapAt to act with it on Cos[y]^2 +Sin[y]^2

Here is how you do this. The expression to be simplified is w defined below. I use MapAt to act with the function

	Function[x,1]
	
on w at the position where Cos[y]^2 + Sin[y]^2 is located. The expression Function[x,1] is a new syntax that I will explain shortly. Now let us see whether the program shown below does what I intended

w=a x^2 +3 (Cos[y]^2+Sin[y]^2)^(1/2) 
w1=MapAt[Function[x,1],w,Position[w,Cos[y]^2+Sin[y]^2]] 
Clear[w]

The output is the expression 

	x^2 +3 (Cos[y]^2+Sin[y]^2)^(1/2)
	
in which Cos[y]^2 + Sin[y]^2 was replaced with 1.  The program works.

The new syntax 
	Function[nameOfArgument, bodyOfFunction] 
is worth remembering.  It defines a nameless function which has the argument nameOfArgument and a set of expressions called bodyOfFunction which defines the operations performed by the function. This can be used like any other nameless function. Here are a few examples of such function definitions.

Below I Map the function 
	(x^2) +3 (x^3)
into the list {a, b, c}

Function[x,x^2+3 x^3]/@{a,b,c}

We can define functions of two variables in this way, as you see below. Here the function 
	(x^2) + 3 sin[y] 
is used in MapThread to act on the pair of lists {{a, b, c},{A, B, C}}

MapThread[Function[{x,y},x^2+ 3 Sin[y]],{{a,b,c},{A,B, C}}]

In the next example I use the nameless function 
	List[#1, #2, #3]&
to turn the list
	{{a,b,c},{A,B,C},{1,2,3}}
into
	{{a,A,1},{b,B,2},{c,C,3}}

MapThread[List[#1,#2,#3]&,{{a,b,c},{A,B,C},{1,2,3}}]

You can do the same thing by using the nameless function
	Function[{x,y,z},{x,y,z}]

MapThread[Function[{x,y,z},{x,y,z}],{{a,b,c},{A,B,C},{1,2,3}}]

Cell 6: The use of the function Outer to act on the elements of lists

We are often in the situation described in the following example: use the function 
	p[T,v]
to calculate  the pressure, for the temperatures and the molar volumes given in the two lists below
	tempList={T1, T2, T3, T4, .....T10}
	volList={v1, v2, v3, .....v10}
To be clear: I want to calculate
	{ {p[T1, v1], p[T1, v2], p[T1, v3], ...},{ p[T2, v1], p[T2, v2],...},.. etc}

This is very handily done with the function Outer. Here is how this function works:

Clear[f]
Outer[f,{a,b,c},{1,2,3,4,5}]

{

Exercise: Use Table to obtain the same result

The function produces a list of lists. The first list  contains {f[a,1],f[a,2],f[a,3],f[a,4],f[a,5]} which is the function applied to the first element of the first list and each element of the second list, etc. You can see better the structure of the output if you display it with TableForm

%//TableForm

I will discuss TableForm in more detail later. For now you see that it displays the first list in {firstList, secondList, ....} as a row, then secondList as the second row etc.

Let us use this to perform a calculation in Physical Chemistry. I want to know how the pressure of ethane depends on temperature and volume and I plan to use the Benedict Web Rubin equation to do this. The equation is:

	p=RTρ + (BRT-A-(Subscript[C, 0])T-2)r2 +(bRT-a)r3+aa r6+cT-2r3 (1+gr2 ) exp[-((γρ)^2)]
	
The parameters for ethane are:

	 A = 4.15556 ,    B = 6.27724 10^-2 ,     C0 = 1.79592 10^5 ,    a = 0.34516,
  b = 1.1122 10^-2 ,   c = 3.2767 10^4 ,    α = 2.43389 10^-4,    γ = 1.18 10^-2  
  
  If these parameters are used and if v is in liter/mol and T in degrees Kelvin then the pressure is obtained in atmosphere.

I clear all symbols

Remove["Global`*"]

Next, I define the function. Since I cleared all symbols, I do not have to take excessive precautions out of fear that a, b, c, A, B, C0, α or γ may have been given  some strange values earlier in the day.

Clear[pBWR];
pBWR[T_,v_,parameters_]:=Module[
{R=0.08205,p1,p2,p3,p4,p5,ρ},
 ρ=1/v;
p1=R T ρ;
p2=(B R T-A-C0 T^-2)ρ^2;
p3=(b R T-a)ρ^3;
p4=a α ρ^6;
p5= c T^-2 ρ^3 (1+γ ρ^2) Exp[-γ ρ^2];
(p1+p2+p3+p4+p5)/.parameters];

The parameters are:

Clear[A,B,C0,a,b,c,α,γ]
parametersBWR={A->4.15556 ,B->6.27724 10^-2 ,C0->1.79592 10^5 , a-> 0.34516,b->1.1122 10^-2 ,c->3.2767 10^4 ,α-> 2.43389 10^-4,γ->1.18 10^-2 }

Make a list with the temperatures of interest:

temperature=Table[T,{T,100,500,100}] (*degree Kelvin*)

Make a list with the volumes

volume=Table[v,{v,4,20,4}]

Use Outer to calculate the pressure for all pairs of temperatures and volumes

li=Outer[pBWR[#1,#2,parametersBWR]&,temperature,volume]

I check below that the first list in the list li contains the pressures for the first temperature in the list temperature and all the volumes in the list volume:

pBWR[100,#,parametersBWR]&/@volume

You can check that the second list in li corresponds to the second temperature and all the volumes, etc.

To see better what is going on you can display li with the function TableForm

li//TableForm

The top row corresponds to T=100 and all the volumes in the list volume, etc.

My work is done but the display is unsatisfactory.  I'd like to label this table so that I know what the numbers mean. To do this I include in each row the temperature for which the pressure has been calculated. I do this with the function Prepend, which works as follows:

Prepend[{a,b,c},A]

To place the value of the temperature as the first element in the list of pressures, I use this function with MapThread and Prepend:

li2=MapThread[ Prepend, {li,temperature }]

This has added the temperature in the front of the row containing the pressures corresponding to this temperature. Look at the output to see what I mean.

li2//TableForm

I can see at what temperatures I calculated the pressures. Now I want to create a line above the table that gives the volumes. 
I add a blank to the list of volumes (you'll see shortly why):

li3=Prepend[volume, " "]

Then I prepend the list of volumes to the list of pressures:

toTable=Prepend[li2,li3]

Now the table is much easier to comprehend:

toTable//TableForm

That looks better. There are simpler ways to label a table, but the advantage of this procedure is that it is automated. If you give the computer the temperatures and the volumes, it will follow instructions and prints this table. Other methods requires you to type what the volumes and the temperatures are.

Cell 7: Mathematical operations with the elements of lists.

We often need to perform mathematical operations on a whole list. A very useful function for doing this is Apply.
The syntax is 

	Apply[f, expression]
	
where f is an  head of an expression or a function
The short-hand form is

	f@@expression.
	
Apply replaces the head of expression with f

First, let me remind you that every expression has a head. You can find the head by using the function Head or by looking for the "zero" part

w=(a^2+b)*Sin[x];
Head[w]

You can see why I got this result by looking at the FullForm

w//FullForm

Times wraps around the rest of the expression

You can see the Head by looking at the "zero-th" element of the expression

w[[0]]

You can use Apply to change the head of w. Let's change it to List

w
w//FullForm
List@@w
List@@w//FullForm

Our you can use the short form, which is more common:

List@@w

The product of (a^2)+b with Sin[x] was turned into a list of these two quantities. In other words, Apply turned
	Times[a^2+b, Sin[x]]
into
	List[(a^2)+b, Sin[x]]
One head was replaced with another. Here is another example: replace Times with Plus and turn the product into a sum

w
w//FullForm
Plus@@w
%//FullForm

This turned  
	Times[(a^2)+b,Sin[x]]
into
	Plus[(a^2)+b,Sin[x]]

Here is how you add the members of a list.
The head of {a, b, c} is List

{a,b,c}//Head

{a,b,c}[[0]]

The addition is performed with

Plus@@{a,b,c}

The list was changed into a sum since List[a,b,c] became Plus[a,b,c]

You can use the same procedure to multiply the elements of a list:

li1={a,b,c,d,e,f};
Times@@li1

Mathematica was designed to allow simple operations on each element of a list by operating on the list itself.
Here is how you raise each element of a list to a power

li1
li1^a

You can combine this with other operations to calculate the geometric average of a list.

Sqrt[Plus@@(li1^2)]/Length[li1]

You can add lists of the same length

{a,b,c,d,e,f} +{1,2,3,4,5,6}

You can subtract lists of the same length

{a,b,c,d,e,f} -{1,2,3,4,5,6}

You can multiply two lists of the same length

{a,b,c,d,e,f} {1,2,3,4,5,6}

You can divide the elements of lists of the same length.

{a,b,c,d,e,f} /{1,2,3,4,5,6}

{a,b,c,d,e,f} /{1,2,3,4,5 }

You can combine these operations

Plus@@(({a,b,c,d,e,f} /{1,2,3,4,5,6})^2)

Note the importance of placing the parentheses in the right place. A different placement leads to a different expression.

Plus@@({a,b,c,d,e,f} /{1,2,3,4,5,6})^2

This happens because the addition has precedence over power, so the addition is made first.

You can multiply all elements of a list with the same number:

3*li1

You can divide all the elements of a list with the same number:

li1/3

You can divide the elements of the sublists:

{{a,b,c},{A,B,C}}/3

You can combine several such operations

{{a,b,c},{A,B,C}}/3
Plus@@{{a,b,c},{A,B,C}}/3

{{a,b,c},{A,B,C}}/3
(Plus@@{{a,b,c},{A,B,C}}/3)
Plus@@((Plus@@{{a,b,c},{A,B,C}}/3)^2)

Cell 8:  The use of TableForm to make tables and NumberForm to trim the numbers.

Often we want to make a neat looking table with the data and the results of a calculation. Since the main data containing object is a list, we need to learn how to go from list to tables. This is done with the function TableForm, that you have encountered several times in these lectures. Now you will learn a bit more about this function.

I'll start with a practical problem. You want to calculate the pressure with the Benedict-Web-Rubin equation of state and with the van der Waals equation and you want to compare the results to the experimental data. You want to do this for ethane, for a temperature of 350 K and the molar volumes 

	 v = {28.588, 5.6119, 2.7387, 0.1372, 0.0984, 0.0868,  0.30716, 0.07089, 0.07022} liter/mole. 
	 
In this particular section we are concerned with displaying the results in a nice looking table.

Here is the plan of this calculation
	1. Input the data
	2. Define functions that calculate the pressure with the vdW and the BWR equations
	3. Calculate the pressures and the errors made by the equations
	4. Manipulate the lists with the results to make a table with TableForm
	5. Make the table look nice

Remove["Global`*"]
Needs["Utilities`CleanSlate`"]
CleanSlate[]

Input the data

The molar volumes are

v = {28.588, 5.6119, 2.7387, 0.1372, 0.0984, 0.0868, 
   0.07160, 0.07089, 0.07022} (*liter/mol*)

The measured pressures are:

p = {1, 5, 10, 100, 150, 200, 450, 475, 500} (*atm*)

The parameters for van der Waals equation for ethane are:

paravdw={a->5.562*.987 ,b->0.0638}

The parameters for Benedict-Webb-Rubin equation for ethane are:

paraBWR={A->4.15556 ,B->6.27724 10^-2 ,C0->1.79592 10^5 , a-> 0.34516,b->1.1122 10^-2 ,c->3.2767 10^4 ,α-> 2.43389 10^-4,γ->1.18 10^-2 }

Define functions that calculate the pressure according to the van der Waals equation and the Benedict-Webb-Rubin equation.

The van der Waals equation is 

	p = (RT/(v-b))-(a/(v^2))
	
Below I create a function pvdw[T,v,parameters] that implements the above equation

Clear[pvdw]
pvdw[T_,v_,parameters_]:=Module[{R=0.08205 (*liter atm/mol*) },
		(R T/(v-b)-a/v^2)/.parameters];
SetAttributes[pvdw,HoldAll];
Protect[pvdw];

The Benedict-Webb-Rubin equation is:

p=RTρ + (BRT-A-(Subscript[C, 0])T-2)r2 +(bRT-a)r3+aa r6+cT-2r3 (1+gr2 ) exp[-((γρ)^2)]

I define below a function that implements this equation.

Clear[pBWR]
pBWR[T_,v_,parameters_]:=Module[
{R=0.08205,p1,p2,p3,p4,p5,ρ},
 ρ=1/v;
p1=R T ρ;
p2=(B R T-A-C0 T^-2)ρ^2;
p3=(b R T-a)ρ^3;
p4=a α ρ^6;
p5= c T^-2 ρ^3 (1+γ ρ^2) Exp[-γ ρ^2];
(p1+p2+p3+p4+p5)/.parameters];
SetAttributes[pBWR,HoldAll];
Protect[pBWR];

Let us check that they work. At large molar volume and room temperature they should give the same results.

pvdw[300,100,paravdw]

pBWR[300,100,paraBWR]

Calculate the pressure with the two equations, for the molar volumes in the list v and the temperature of 360 K. Put the results in 
	pvdwList
and
	pBWRList
Then calculate the errors made by the calculations.

v

pvdwList=pvdw[350,#,paravdw]&/@v

pBWRList=pBWR[350,#,paraBWR]&/@v

errorvdw=(pvdwList-p)*100/p

errorBWR=(pBWRList-p)*100/p

Make a table with the results by using TableForm

TableForm takes the lists and prints them on the screen. Each sublist is a row in the table. Look below to see this

TableForm[{{a,b,c,d,e,f,g,h},{1,2,3,4,5,6,7,8}}]

In most cases the lists we deal with are very long and they will get off the screen. You can see this if I try to represent my results:

TableForm[{v,p,pvdwList,errorvdw,pBWRList,errorBWR}]

The table cuts off the data and it is hard to print. We need to rearrange the lists to make them shorter and more convenient to plot. Let me do this for the simple case I started with . I use the function MapThread to rearrange the data in a list with a different structure:

MapThread[f,{{a,b,c},{A,B,C}}]

toTable=MapThread[{#1,#2}&,{{a,b,c,d,e,f,g,h},{1,2,3,4,5,6,7,8}}]

Now the TableForm gives a vertical table

TableForm[{{a,b,c,d,e,f,g,h},{1,2,3,4,5,6,7,8}}]
toTable//TableForm

Let us do the same thing with our pressures and error lists

toTable=MapThread[{#1,#2,#3,#4,#5,#6}&,{v,p,pvdwList,errorvdw,pBWRList,errorBWR}]

This arranged the lists so that the first element is the molar volume, the second is the experimental pressure, the third is the pressure given by the van der Waals, the fourth is the error of the van derWaals equation, the fifth is the pressure according to the BWR equation, and the sixth is the error given by the BWR equation. Each sublist contains the results for a different molar volume. 
	TableForm displays this in a "vertical" fashion.

toTable//TableForm

This is what I wanted. Next we can worry about labelling the table and making a nice display.

Make the table look nice: label it and cut down the number of decimal points.

TableForm has options that allow us to label the rows and the columns of the table.

I will use TableHeadings

TableForm[toTable,TableHeadings->{None,{"v l/mol","(Subscript[p, exp])atm","(Subscript[p, vdw])atm","(Subscript[err, vdw])","(Subscript[p, BWR])atm", "(Subscript[err, BWR])"}}]

How can I improve this table. The first two columns give the experimental data. I should give it as given by the people who made the measurements. The number of decimals tells me how accurate the measurements are. However,  it does not make sense to give the calculated pressures and the errors with more than two decimal points. I can control the number of decimal points with the function NumberForm.

Below I apply NumberForm to each element of pvdwList by using Map (i.e. the short form /@). In NumberForm I ask that the function should keep six digits and two decimals (this is what {6,2} in NumberForm[#,{6,2}]& does)

pvdwList
NpvdwList=NumberForm[#,{6,2}]&/@pvdwList

I do the same for the list errorvdw, but I keep only five digits:

Nerrorvdw =NumberForm[#,{5,2}]&/@errorvdw

NpBWRList=NumberForm[#,{5,2}]&/@pBWRList

NerrorBWR= NumberForm[#,{4,2}]&/@errorBWR

Now make a table with the numerical values rounded off :

toTable=MapThread[{#1,#2,#3,#4,#5,#6}&,{v,p,NpvdwList,Nerrorvdw,NpBWRList,NerrorBWR}];
TableForm[toTable,TableHeadings->{None,{"v l/mol","(Subscript[p, exp])atm","(Subscript[p, vdw])atm","(Subscript[err, vdw])","(Subscript[p, BWR])atm", "(Subscript[err, BWR])"}}]

These steps did what we wanted. The function TableForm has a lot of options that allow you to control the spacing between the rows and the columns, the way you line up the numbers in the columns, and all kinds of other beautifying measures. If you have nothing better to do you can look them up in Wolfram's book. What you learn here suffices.

I mention two other functions that allow you to manipulate the look of the numbers.

ScientificForm[#,2]&/@errorBWR

The second argument in ScientificForm (i.e. 2 in our case) controls the number of decimals.

EngineeringForm[# ]&/@errorBWR

EngineeringForm[# ,3]&/@errorBWR

EngineeringForm[# ,4]&/@errorBWR

Cell 9:  Adding or removing elements of a list: Take, Drop, Delete, Append, Prepend, Insert, First, Last, Rest, ReplacePart

Take[list, position] picks some elements from the argument list indicated by the argument position

You can pick the first 3 elements:

Take[{a,b,c,d,e,f,g},3]

You can take the third element and place it in a list by itself

Take[{a,b,c,d,e,f,g},{3}]

You can pick the last two elements:

Take[{a,b,c,d,e,f,g},-2]

You can pick all the elements between second and forth, including the second and the fourth

Take[{a,b,c,d,e,f,g,h,i},{2,4}]

Drop[list,position] removes from the list  the elements indicated by position

Remove the first three elements

Drop[{1,2,3,4,5,6,7,8},3]

Remove the last two elements

Drop[{1,2,3,4,5,6,7,8},-2]

Remove the elements in position 2 through 5 (the limits included)

Drop[{1,2,3,4,5,6,7,8},{2,5}]

Drop treats each inner list like one element (see below)

Drop[{1,2,{3,4,5,6},7,8},3]

Drop[{1,2,3,4,6},{4}]

Delete[list,position] removes from the list in the argument the elements indicated by position

Delete[{1,2,3,4,5,6,7,8},3 ]

Delete[{1,2,3,4,5,6,7,8},-2 ]

Delete[{1,2,3,4,5,6,7,8},{{2},{4}} ]

The function Delete works well with the function Position

w={a,b,a,c,r,t};
Delete[w,Position[w,b]]
Delete[w,Position[w,a]]

Exercise: I made below a function which removes an element (whichever you want) from a given list.
Explain how it works

f[list_List,element_]:=Delete[list,Position[list,element]]

f[{a,b,a,c,d,e,f},a]

First[list], Last[list], Rest[list] return the first element of the list, the last element of the list and the list without the first element

First gives the first element of the list:

First[{a,b,c,d,e}]

Last gives the last element of a list.

Last[{a,b,c,d,e}]

Rest gives the list without the first element

Rest[{a,b,c,d,e}]

Insert[list, element, position] returns the list with element added at the position specified by position

Insert 10 in the third position of the resulting list

Insert[{a,b,c,1,2,3},10,3]

ReplacePart[expression, newPart, position] replaces in expression the part at the position given by position with the newPart

Below I replace the third part of the list {a,b,A, D,1.2, 17,22} with Cos[x]

ReplacePart[{a,b,A, D,1.2, 17,22},Cos[x],3]

Below I combine ReplacePart with the function Position to replace in the expression 
	a^2 Cos[x]/b+Log[Sqrt[Cos[x]]
the part 
	Log[Sqrt[Cos[x]]]
with the new part.  
	Sin[Sqrt[Cos[x]]]
I used the pattern Log[_] in Position to match Log[Sqrt[Cos[x]]]

ReplacePart[w=a^2 Cos[x]/b+Log[Sqrt[Cos[x]]] ,Sin[Sqrt[Cos[x]]],Position[w,Log[_]] ]

w/.Log->Sin

Cell 10: Other functions acting on lists: Length, Select

Length[list] tells us how many elements are in the list

I will work with several lists, labelled li1, li2, li3

li1={1,2,3,4,5,6,7,8};
li2={a,b,c,d,e,f,g,h, i , j, k};
li3={{a,b,c},{1,2,3, 4,5,6},A};

If I want to know how many elements are in a list I use the function Length.

{Length[li1],Length[li2],Length[li3]}

Note the third result: the list li3 is of length 3. This is right: it contains three elements, two of which are lists. If I want to know the length of an internal list I use MapAt. I'll let you decipher how the lines below works

li3

MapAt[Length,li3,1]
MapAt[Length,li3,1][[1]]

MapAt[Length,li3,2]
MapAt[Length,li3,2] [[2]]

li3
Take[li3,{1}]
Take[li3,{1}]//Flatten
Take[li3,{1}]//Flatten//Length

You can use Length in many ways. One is to calculate average values of the numbers in a List.

I generate a list of numbers that consist of 2 plus a random number between -0.1 and 0.1. The random numbers are generated by the function Random[Real,{-0.1,0.1}] which produces a random real number between -0.1 and 0.1

Random[Real,{-0.1,0.1}]

I can produce ten random numbers in that range

Table[Random[Real,{-.1,.1}],{i,1,10}]

Here is the list of data whose average I want to calculate:

listOfData=Table[2+Random[Real,{-0.1,0.1}],{i,1,50}]

The average is the sum of all numbers in the list divided by the number of elements in the list:

average=Plus@@listOfData/Length[listOfData]

The mean square deviation of the data in the list a={(Subscript[a, 1]), (Subscript[a, 2]), (Subscript[a, 3]), ...(Subscript[a, N])} is 

	(Sqrt[(∑_(i=1)^N)((((Subscript[a, i])-⟨a⟩))^2)/N])
where 
	⟨a⟩=(∑_(i=1)^N)(Subscript[a, i])/N
	
is the average value of the data in the list. Write a function that calculates the mean square deviation of the data in the list listOfData

mSD[a_List]:=Module[{average},
average=Plus@@a/Length[a];
Sqrt[Plus@@((#-average)^2& /@a) ]/Length[a]
]

mSD[listOfData]

Exercise: write a function that returns a list containing {average, meanSquareDeviation}

Select[list, condition] makes a new list with the elements of list for which condition gives True

Select is another useful function that allows us to pick out of a list the elements that satisfy a certain condition and make a list with them. Part of the art of using this function is to formulate a condition that returns True or False when applied to an element of the list. Select retains those elements for which the condition returns true. 
	The syntax is 
	Select[list,condition]
I'll show you how works, by example.

I want to select the elements of the list that are larger than 3.

Select[{1,5,2,7,a,9},#>3&]

For the condition I used the nameless function
	#>3&
To see how this function works I Map it (with /@ ) into the list {1, 5, 2, 7, a, 9}

#>3&/@{1,5,2,7,a,9}

Select picks the elements for which the function returns True. Since a is a symbol the function returns a>3 (can't decide whether a is greater or less than 3. Since this is not True, Select ignores a (does not pick it)

Exercise:  I created a function 
	select[list,condition]
that does the same thing as select. Explain how it works

Clear[select]
select[list_,cond_]:=Module[{w1,w2,w3},
w1=cond/@list;
w2=Position[w1,True];
w3=Take[list,#]&/@w2;
  w3//Flatten]

select[ {1,5,2,7,a,9},#>3&]

You can select the integers in a list, by using IntegerQ . Here is how IntegerQ works:

IntegerQ[3]
IntegerQ[2.3]
IntegerQ/@{1,2.3,4,1.2,3}

Here is how you use it to select integers from the list

Select[{1,2.3,4,1.2,3},IntegerQ]

?*Q

You can use a different condition. The function 
	(Head[#] ===Integer)&
does the same thing as IntegerQ (it checks if the Head of an expression is an integer )

Head[3]===Integer

Head[2.3]===Integer

Head[#]===Integer&/@{1,2.3,4,1.2,3}

You can use the function
	Head[#]= = =Integer&
in Select

Select[{1,2.3,4,1.2,3},Head[#] ===Integer&]

You can pick up the complex numbers in a list:

2.3+I 5.4//FullForm

Select[{3.2, 2.1+I 3.2,2.1 I, 3,a},Head[#]===Complex&]

You can pick the real numbers in a list

Select[{3.2, 2.1+I 3.2,2.1 I, 3,a},Head[#]===Real&]

You can pick the symbols in a list

Select[{3.2, 2.1+I 3.2,2.1 I, 3,a},Head[#]===Symbol&]

Head[a]

You can pick the members of a list that are themselves lists:

Select[{a,{1.2,3,2.3},{A,B,C},17.2},Head[#]===List&]

Here is an example where I use Select. I solve an equation of high order and I want to keep only the real roots

Clear[sol]
sol= NSolve[3 x^5+2 x^4+5.3 x^2+12 x-3.4==0,x]

The above is a list of replacement rules for the solutions of the equation. I want to use Select to pick up the real solutions.
To do this I need to have a list with the solutions, rather than have a list of rules. I can convert the rules to the solutions with the pattern matching 
	sol/.{x_->y_}->y
This tells the computer to look in the expression sol, find all patterns of the form  something->somethingElse and replace them with somethingElse (see below the effect)

sol1=sol/.{x_->y_}->y

sol1

sol1/.Complex[x_,y_]->y

Now use Select with the condition  
	Head[#]===Real&
to pick up the real numbers among the solutions

so2=Select[sol1,Head[#]===Real&]

Normally, the solution of an equation are given in the form of a replacement rule. We can turn the above expression into a replacement rule as follows:

Rule[x,y]

Rule[x,#]&/@so2

Exercise:  I will create the function 
	realSolutions[ex,vary]
which returns the real solutions of the polynomial equation ex in the variable vary

realSolutions[eq_,var_]:=Module[{sol1,w1},
sol1=NSolve[eq,var]/.{x_->y_}->y;
w1=Select[sol1,Head[#]===Real&];
If[Length[w1]==0,Print["There is no real solution"],
Rule[var,#]&/@w1]
]

Note that I used a new statement
	Print["There is no real solution"]
which prints this message when there is not real solution (in that case the Length of the list with the real solution is zero)

Let' check that the function works as desired

realSolutions[3 x^5+2 x^4+5.3 x^2+12 x-3.4==0,x]

realSolutions[12.3 x^5+3.9 x^4+18 x-8.5==0,x]

Let us automate the creation of a polynomial equation of order n with the function 
	eq[n,x]

eq[n_,x_]:=Plus@@Table[Random[]*x^i,{i,0,n}]==0

Let's see whether this works.

eq[5,z]

The coefficients of the equation are picked at random (by using the function Random[]) so each use of the function eq produces a new equation.

realSolutions[eq[5,x],x]

realSolutions[eq[5,x],x]

realSolutions[eq[5,x],x]

realSolutions[eq[5,x],x]

realSolutions[eq[5,x],x]

realSolutions[eq[4,x],x]

realSolutions[eq[4,x],x]

realSolutions[eq[4,x],x]

realSolutions[eq[4,x],x]

Cell 11: Functions that change the structure of lists: Transpose, Flatten, Sort

Transpose[{{list1},{list2},...{listn}}]

Transpose is best understood if you think of a list of lists as a matrix. Then Transpose will transpose the matrix. Here is how this works:

Make a list

li={{a,b,c,d,e,f},{A,B,C,D,E,F}}

Use MatrixForm to display it as a matrix:

{{a,b,c,d,e,f},{A,B,C,D,E,F}}//MatrixForm

The list corresponds to a 2X6 matrix. Now transpose the list:

Transpose[{{a,b,c,d,e,f},{A,B,C,D,E,F}}]

Look at the matrix form of the output

%//MatrixForm

The function Transposed turned a 6X2 matrix into a 2X6 one. This is what transposing a matrix means.

You can transpose a list of three lists:

{{a,b,c},{A,B,C},{1,2,3}}//MatrixForm

Transpose[{{a,b,c},{A,B,C},{1,2,3}}]
%//MatrixForm

Transpose if very useful when we deal with matrix algebra. It also used often when we want to make tables with data. Here is an example

li={{a,b,c,d,e,f,g,h,i,j,k,l,m,n},{A, B, C, D, E,F,G,H,I,J,K,L,M,N}}

li//TableForm

For a long list of data this becomes hard to read. It is better to plot

Transpose[li]//TableForm

Flatten

We have already used Flatten in the previous lectures. Here is how it works:

Make a complicated list named w:

w={{a,b,c},{A,B,C,{1,2,3,{g, m, f,q}}},U,H}

w//TreeForm

Flatten it:

Flatten[w ]//FullForm

To understand how Flatten works let's look at the FullForm of our list w

w//FullForm

The head of the expression is List and then there are several inner expressions which also have the head List. Flatten removes all heads identical to the first head.  It works not only with lists but on any expression:

Flatten[f[f[f[x]]]]

All the internal heads f that are identical to the first head have been removed.

You can control how deep in the expression Flatten goes.

w
w//TreeForm
Flatten[w,1]
Flatten[w,1]//TreeForm

The above flattened at the first level of w but left the list {1,2,3,{g,m,f,q}} untouched. It acts similarly on other expressions. This also works for an expression with an arbitrary head f:

Flatten[f[f[f[x]]],1]

We can Flatten to the second level

w
w//TreeForm
Flatten[w,2]

That left the inner list {g,m,f,q} untouched (this sublist is on the third level)

w
Flatten[w,3]

You can combine Flatten with MapAt to Flatten very selectively inside a list or an expression.

w
MapAt[Flatten[#]&,w, Position[w,{1,2,3,{g,m,f,q}}]]

Try to decipher the line written above: it maps Flatten on the list {1,2,3,{g,m,f,q}} to flatten it; it does this by using MapAt combined with Position (to find where the list we want to Flatten is located).

Turn the expression 
	f[f[g[f[f[x]]]]]
into 
	f[f[g[f[x]]]]

w=f[f[g[f[f[x]]]]]
MapAt[Flatten[#]&,w,Position[w,f[f[x]]]]

We use Flatten very often because many functions that return lists do not have the structure we need for later use. This is typical in the case when we use Solve, NSolve, DSolve and other functions. Here is an example:

sol=Solve[{2 x+4 y==3,1.2 x+4.3 y==2.1},{x,y}]

If I want to calculate the square of the solution I do this:

x^2/.sol

This returns the result in a list. If I want to have a result as a number I have to Flatten sol:

x^2/.(sol//Flatten)

Sort

Often we want to order a list of numbers in increasing order or a list of letters in alphabetical order. Sort allows us to do this. For example:

Sort[{a,d,c,e,t,h}]

Sort[{1.2, 3.2,0.02,7,4.5}]

Sort[{3,2,4,a,b}]

If you want to have the reversed order (largest number, next large number etc) use Reverse[Sort[list]]

Reverse[Sort[{1.2, 3.2,0.02,7,4.5}]]

Reverse[Sort[{3,2,4,a,b}]]

Cell 12: Functions that combine lists: Join, Union, Complement, Intersection

Join[list1,list2] combines list1 with list2 into one list.

Join[{a,b,c,1,4,3,7},{a,B,D,4,5}]

Join can take more than two lists as arguments

Join[{a,b,c},{1,2,3,4,5}, {Sin[x], Log[x]}]

Union[list1, list2] combines list1 and list2  to form a new list from which it drops all common elements (no duplicates) and then sorts them (first numbers in increasing order, next  letters in alphabetical order ( if the list contains a and A the order is a, A )

Union[{a,b,c,1,4,3,7},{a,B,D,4,5}]

Union[{a,b,4},{2,5,4,e},{A,B,Sin[c]}]

Complement[list1,list2] makes a list with all the elements that list1 does not have in common with list2.

Complement[{a,b,c,1,4,3,7},{a,B,D,4,5}]

Intersection[list1,list2] makes a list with all the elements in list1 that are contained in list2

Intersection[{a,b,c,1,4,3,7},{a,B,D,4,5}]

You can combine these functions: figure out what the function shown below does.

Complement[Union[{a,b,c,1,4,3,7},{a,B,D,4,5}],Intersection[{a,b,c,1,4,3,7},{a,B,D,4,5}]]

Complement[Union[{a,b,c,1,4,3,7},{a,B,D,4,5}],Intersection[{a,b,c,1,4,3,7},{a,B,D,4,5}]]//Trace