# graphing problems in metapost

I have some data as follows (first and second columns) in the file mydata.d that I want to graph:

8   98826   year 2008
9   104925  year 2009
10  140153  year 2010
11  178414  year 2011


As we have big numbers in the second numbers, I have used the macro sarith. Here's my metapost code for the plot:

input graph
input sarith
beginfig(1);
draw begingraph(8cm,5cm);
setrange(8,whatever,12,whatever);
gdraw "mydata.d" withpen pencircle scaled 1.5pt;;
gdraw "mydata.d" plot btex $\bullet$ etex;
autogrid(otick.bot,);
gdotlabel.lrt(btex $98\;826$ etex, 8,"98826");
gdotlabel.lrt(btex $104\;925$ etex, 9,"104925");
gdotlabel.lrt(btex $140\;153$ etex, 10,"140153");
gdotlabel.lrt(btex $178\;414$ etex, 11,"178414");
endgraph;
endfig;
end


So I am plotting the first two columns, taking away the y-axis tickmarks and labels and also writing the y-value at each coordinate in the plot. I have the following questions:

1. I wanted to show the year i.e. 2008 to 2010 but metapost just shows 2010 along the x-axis and this is why I have chosen the numbers 8 to 10 instead. Why is that?

2. If you plot the curve, you would see two dots at each coordinate where the corresponding y-value is written. Why is this happening? This occurs even if I take away the line gdraw mydata.d" plot btex $\bullet$ etex. In the gdotlabel lines, I have to include the numbers in the second column in quotes e.g. "98826". Is this causing a problem for metapost to be accurate at such a large numbers and hence the appearance of two dots?

3. If from 1 we can show the year 2008, 2009, 2010 and 2011 well, then how can we display them but rotated say 90 degree anticlockwise so that the labels do not take too much space horizontally?

4. If I ask metapost to display the y values on the y-axis, well it will write in exponential form instead of pure decimal form like 100000, 150000 etc. How to achieve this?

5. I understand that metapost ignores columns other than the two columns and this is useful to write comments pertaining to that line e.g. year 2008 on the first line. However if I would like to add a global comment to the whole file such as "Number of apples I ate in each year", then I cannot do this in the beginning of the file. I presume that we can do it at the end of the file, but how? I have tried leaving blank spaces and starting the comment line with a % sign but this doesn't work.

I am using TeXLive 2010 under Win XP with MetaPost, version 1.211. I also tried TL 2011 with MetaPost 1.504.

Thanks a lot for your kind help...

I know this is old, but there are some fairly simple answers to the questions so I thought I would have a go. And even though I am a fan of MP, I think that I would agree with @percusse that pgfplots is probably better than input graph in MP.

I'll get to the list of questions in a minute, but first we can simplify things a bit. The correct form for the MP graph input is like this:

2008   98826  Your comments go here
2009  104925
2010  140153
2011  178414


so I am going to assume that you have changed mydata.d to this format.

Given this data file we can produce a graph with just a single gdraw line.

prologues := 3;
outputtemplate := "%j%c.eps";

input graph

beginfig(1);
draw begingraph(160, 100);
gdraw "mydata.d" withpen pencircle scaled 1/2 withcolor 2/3 red;
endgraph;
endfig;
end.


I added some options to make the line in red with a nice weight. This produces:

And we can immediately see the first problem, the years have all been printed as "2010". Some careful reading of the manual, tells us that this is because the default precision for all numeric labels is 3 significant figures. So all the years have been rounded to the nearest 10.

The command that does this is the implicit autogrid that is added by the endgraph command by default. In order to fix this we have to format our labels semi-manually, as explained towards the end of section 2.2 in the manual. Changing our source like this:

prologues := 3;
outputtemplate := "%j%c.eps";

input graph

beginfig(1);
draw begingraph(160, 100);
gdraw "mydata.d" withpen pencircle scaled 1/2 withcolor 2/3 red;
for x=auto.x: otick.bot(format("%4g", x), x); endfor
for y=auto.y: otick.lft(format("%g", y), y); endfor
endgraph;
endfig;
end.


produces a better result. What we have done here is round the years to 4 significant figures.

The second problem was to put a dot mark at each data point neatly. The correct way to do this is to add the plot option to the gdraw command. The OP issue was that using plot btex $\bullet$ etex puts the dots in the wrong places. The manual does explain this as well, but not very clearly. My recommendation is that you make your own dot marks in MP, like this:

prologues := 3;
outputtemplate := "%j%c.eps";

input graph

picture bullet; bullet = image(drawdot origin withpen pencircle scaled 2);

beginfig(1);
draw begingraph(160, 100);
gdraw "mydata.d" plot bullet withpen pencircle scaled 1/2 withcolor 2/3 red;
for x=auto.x: otick.bot(format("%4g", x), x); endfor
for y=auto.y: otick.lft(format("%g", y), y); endfor
endgraph;
endfig;
end.


to produce this:

The third question was "how to rotate the year labels"? To do this we need to provide a function to use instead of the format function. The output should be a picture object. Here is one way to do it:

prologues := 3;
outputtemplate := "%j%c.eps";

input graph

picture bullet; bullet = image(drawdot origin withpen pencircle scaled 2);
vardef year_label(expr Y) = decimal Y infont "cmr10" rotated 60 enddef;

beginfig(1);
draw begingraph(160, 100);
gdraw "mydata.d" plot bullet withpen pencircle scaled 1/2 withcolor 2/3 red;
for x=auto.x: otick.bot(year_label(x), x); endfor
for y=auto.y: otick.lft(format("%g", y), y); endfor
endgraph;
endfig;
end.


Now the graph look like this. You can play about with the rotation angle, if you really want it at 90°.

The fourth question was about the y-axis labels. The problem here is also about rounding, but we can't just change the precision, as we did for the years, because the absolute values are greater than 4096, so graph is automatically using MP's string arithmetic, and so the formatting rules are subtly different (and not very good in my opinion). If you really want lots of zeros, then the best that I can suggest is that we put the labels in "by hand":

prologues := 3;
outputtemplate := "%j%c.eps";

input graph

picture bullet; bullet = image(drawdot origin withpen pencircle scaled 2);
vardef year_label(expr Y) = decimal Y infont "cmr10" rotated 60 enddef;

beginfig(1);
draw begingraph(160, 100);
gdraw "mydata.d" plot bullet withpen pencircle scaled 1/2 withcolor 2/3 red;
for x=auto.x: otick.bot(year_label(x), x); endfor

otick.lft("100,000" infont "cmr10", "100000");
otick.lft("140,000" infont "cmr10", "140000");
otick.lft("180,000" infont "cmr10", "180000");

endgraph;
endfig;
end.


to produce this:

but the obvious drawback is that you have to know the data range to put the labels in the right places. So I think my final effort would be to reduce the size of the y values by transforming them, and adding a scale label to the axis:

prologues := 3;
outputtemplate := "%j%c.eps";

input graph
input sarith

picture bullet; bullet = image(drawdot origin withpen pencircle scaled 2);
vardef year_label(expr Y) = decimal Y infont "cmr10" rotated 60 enddef;

beginfig(1);
draw begingraph(160, 100);
gdraw "mydata.d" plot bullet withpen pencircle scaled 1/2 withcolor 2/3 red;
for x=auto.x: otick.bot(year_label(x), x); endfor
for y=auto.y: otick.lft(format("%g", y Sdiv "1000"), y); endfor
glabel.lft("Thousands" infont "cmr8" rotated 90, OUT);
endgraph;
endfig;
end.


Like so:

The answer to the fifth question about putting global comments at the top and bottom is "don't do that". Put your global comments to the right of the first few columns.

You can put comments after the blank line that finishes each data set, but beware that if you read the file more than once (as the OP did) then your comment might be mistaken for a second data set. So I recommend that you don't do that.

• Even if it's old, you have to appreciate a long and well done job. – Sebastiano Dec 30 '19 at 16:48

I would strongly suggest using pgfplots for such plots. Here is an example including data commenting, year handling thousands separations etc. :

\documentclass{article}
\usepackage{pgfplots}

\pgfplotstableread[skip first n = 4]{%
% Some TeX comment
Comment line
The number days that the doctor
will be kept away...
Comment end
year n
2008 98826
2009 104925
2010 140153
2011 178414
}\mytable

\begin{document}
\begin{tikzpicture}
\begin{axis}[scaled ticks=false,
xtick=data,
xticklabel={\pgfmathprintnumber[fixed,1000 sep=]{\tick}},
xticklabel style={rotate=90},
yticklabel={\pgfmathprintnumber[int detect,fixed,1000 sep={\;}]{\tick}}
]