Plot coordinate pairs

From Rosetta Code

Jump to: navigation, search
Task
Plot coordinate pairs
You are encouraged to solve this task according to the task description, using any language you may know.

Plot a function represented as `x', `y' numerical arrays.

Post link to your resulting image for input arrays (see Example section for Python language on Query Performance page):

x = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
y = {2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0};

This task is intended as a subtask for Measure relative performance of sorting algorithms implementations.

Contents

[edit] C

We could use the suite provided by Raster graphics operations, but those functions lack a facility to draw text.

Library: libplot

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <plot.h>
 
#define NP 10
double x[NP] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
double y[NP] = {2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0};
 
void minmax(double *x, double *y,
double *minx, double *maxx,
double *miny, double *maxy, int n)
{
int i;
 
*minx = *maxx = x[0];
*miny = *maxy = y[0];
for(i=1; i < n; i++) {
if ( x[i] < *minx ) *minx = x[i];
if ( x[i] > *maxx ) *maxx = x[i];
if ( y[i] < *miny ) *miny = y[i];
if ( y[i] > *maxy ) *maxy = y[i];
}
}
 
/* likely we must play with this parameter to make the plot looks better
when using different set of data */

#define YLAB_HEIGHT_F 0.1
#define XLAB_WIDTH_F 0.2
#define XDIV (NP*1.0)
#define YDIV (NP*1.0)
#define EXTRA_W 0.01
#define EXTRA_H 0.01
#define DOTSCALE (1.0/150.0)
 
#define MAXLABLEN 32
 
#define PUSHSCALE(X,Y) pl_fscale((X),(Y))
#define POPSCALE(X,Y) pl_fscale(1.0/(X), 1.0/(Y))
#define FMOVESCALE(X,Y) pl_fmove((X)/sx, (Y)/sy)
 
int main()
{
int plotter, i;
double minx, miny, maxx, maxy;
double lx, ly;
double xticstep, yticstep, nx, ny;
double sx, sy;
 
char labs[MAXLABLEN+1];
 
plotter = pl_newpl("png", NULL, stdout, NULL);
if ( plotter < 0 ) exit(1);
pl_selectpl(plotter);
if ( pl_openpl() < 0 ) exit(1);
 
/* determines minx, miny, maxx, maxy */
minmax(x, y, &minx, &maxx, &miny, &maxy, NP);
 
lx = maxx - minx;
ly = maxy - miny;
pl_fspace(floor(minx) - XLAB_WIDTH_F * lx, floor(miny) - YLAB_HEIGHT_F * ly,
ceil(maxx) + EXTRA_W * lx, ceil(maxy) + EXTRA_H * ly);
 
/* compute x,y-ticstep */
xticstep = (ceil(maxx) - floor(minx)) / XDIV;
yticstep = (ceil(maxy) - floor(miny)) / YDIV;
 
pl_flinewidth(0.25);
 
/* compute scale factors to adjust aspect */
if ( lx < ly ) {
sx = lx/ly;
sy = 1.0;
} else {
sx = 1.0;
sy = ly/lx;
}
 
pl_erase();
 
/* a frame... */
pl_fbox(floor(minx), floor(miny),
ceil(maxx), ceil(maxy));
 
/* labels and "tics" */
pl_fontname("HersheySerif");
for(ny=floor(miny); ny < ceil(maxy); ny += yticstep) {
pl_fline(floor(minx), ny, ceil(maxx), ny);
snprintf(labs, MAXLABLEN, "%6.2lf", ny);
FMOVESCALE(floor(minx) - XLAB_WIDTH_F * lx, ny);
PUSHSCALE(sx,sy);
pl_label(labs);
POPSCALE(sx,sy);
}
for(nx=floor(minx); nx < ceil(maxx); nx += xticstep) {
pl_fline(nx, floor(miny), nx, ceil(maxy));
snprintf(labs, MAXLABLEN, "%6.2lf", nx);
FMOVESCALE(nx, floor(miny));
PUSHSCALE(sx,sy);
pl_ftextangle(-90);
pl_alabel('l', 'b', labs);
POPSCALE(sx,sy);
}
 
/* plot data "point" */
pl_fillcolorname("red");
pl_filltype(1);
for(i=0; i < NP; i++)
{
pl_fbox(x[i] - lx * DOTSCALE, y[i] - ly * DOTSCALE,
x[i] + lx * DOTSCALE, y[i] + ly * DOTSCALE);
}
 
pl_flushpl();
pl_closepl();
}

No one would use the previous code to produce a plot (that looks this way; instead, normally we produce data through a program, then we plot the data using e.g. gnuplot or other powerful tools; the result (with gnuplot and without enhancement) could look like this instead.

[edit] gnuplot

Example gnuplot output
unset key  # Only one data set, so the key is uninformative
 
plot '-' # '-' can be replaced with a filename, to read data from that file.
0 2.7
1 2.8
2 31.4
3 38.1
4 68.0
5 76.2
6 100.5
7 130.0
8 149.3
9 180.0
e


[edit] F#

Using the F# for Visualization library:

alt text
#r @"C:\Program Files\FlyingFrog\FSharpForVisualization.dll"
 
let x = Seq.map float [|0; 1; 2; 3; 4; 5; 6; 7; 8; 9|]
let y = [|2.7; 2.8; 31.4; 38.1; 58.0; 76.2; 100.5; 130.0; 149.3; 180.0|]
 
open FlyingFrog.Graphics
 
Plot([Data(Seq.zip x y)], (0.0, 9.0))

[edit] Haskell

gnuplot is a package from HackageDB.

import Graphics.Gnuplot.Simple
 
pnts = [2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0]
 
doPlot = plotPathStyle [ ( Title "plotting dots" )]
(PlotStyle Points (CustomStyle [])) (zip [0..] pnts)

[edit] HicEst

REAL :: n=10, x(n), y(n)
 
x = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
y = (2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0)
 
WINDOW(WINdowhandle=wh, Width=-300, Height=-300, X=1, TItle='Rosetta')
AXIS(WINdowhandle=wh, Title='x values', Yaxis, Title='y values')
LINE(X=x, Y=y, SymbolDiameter=2)

File:HicEst_plot_coordinate_pairs.png

[edit] J

Library: plot

require 'plot'
X=: i.10
Y=: 2.7 2.8 31.4 38.1 58.0 76.2 100.5 130.0 149.3 180.0
'dot; pensize 2.4' plot X;Y

Output of plot.

[edit] Mathematica

x={0,1,2,3,4,5,6,7,8,9};
y={2.7,2.8,31.4,38.1,58.0,76.2,100.5,130.0,149.3,180.0};
ListPlot[{x, y} // Transpose]

Output: [1]

[edit] MATLAB

>> x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
>> y = [2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0];
>> plot(x,y,'.-')

[edit] Maxima

(%i1) ".." (m, n) := makelist (i, i, m, n); infix ("..")$
(%i2) x: 0 .. 9$ y:[2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0]$
(%i3) plot2d(['discrete, x, y], [style, [points,5,1,1]], [gnuplot_term, png], [gnuplot_out_file, "qsort-range-10-9.png"])$

qsort-range-10-9.png

[edit] OCaml

#load "graphics.cma"
open Graphics
 
let round x = int_of_float (floor(x +. 0.5))
 
let x = [0; 1; 2; 3; 4; 5; 6; 7; 8; 9]
and y = [2.7; 2.8; 31.4; 38.1; 58.0; 76.2; 100.5; 130.0; 149.3; 180.0]
 
let () =
open_graph "";
List.iter2
(fun x y ->
(* scale to fit in the window *)
let _x = x * 30
and _y = round(y *. 2.0) in
plot _x _y)
x y;
ignore(wait_next_event [Key_pressed]);
close_graph();
;;

[edit] Octave

x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
y = [2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0];
plot(x,y,"o");
pause;

[edit] Perl

Library: GD::GraphGraph

use GD::Graph::points;
 
@data = (
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0],
);
$graph = GD::Graph::points->new(400, 300);
$gd = $graph->plot(\@data) or die $graph->error;
 
# Save as image.
$format = $graph->export_format;
open(OUF, ">qsort-range-10-9.$format");
binmode OUF;
print OUF $gd->$format();
close(OUF);

Library: Imager Library: Imager::PlotPlot

use Imager;
use Imager::Plot;
 
@x = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
@y = (2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0);
$plot = Imager::Plot->new(
Width => 400,
Height => 300,
GlobalFont => 'PATH_TO_TTF_FONT',
);
$plot->AddDataSet(
X => \@x,
Y => \@y,
style => {
marker => {
size => 2,
symbol => 'circle',
color => Imager::Color->new('red'),
},
},
);
$img = Imager->new(
xsize => 500,
ysize => 400,
);
$img->box(filled => 1, color => 'white');
$plot->Render(Image => $img, Xoff => 50, Yoff => 350);
$img->write(file => 'qsort-range-10-9.png');

[edit] PicoLisp

Example picoLisp output
(load "@lib/ps.l")
 
(scl 1)
 
(de plot (PsFile DX DY Lst)
(let (SX (length Lst) SY (apply max Lst) N 0 Val)
(out PsFile
(psHead (+ DX 20) (+ DY 40))
(font (9 . "Helvetica"))
(if (or (=0 SX) (=0 SY))
(window 60 12 DX DY
(font 24 ,"Not enough Data") )
(setq Lst # Build coordinates
(let X -1
(mapcar
'((Y)
(cons
(*/ (inc 'X) DX SX)
(- DY (*/ Y DY SY)) ) )
Lst ) ) )
(color 55 95 55 # Background color
(let (X (+ DX 40) Y (+ DY 40))
(poly T 0 0 X 0 X Y 0 Y 0 0) ) )
(window 20 20 DX DY # Plot coordinates
(poly NIL 0 0 0 DY (- DX 20) DY)
(color 76 24 24
(poly NIL (caar Lst) (cdar Lst) (cdr Lst)) ) )
(window 4 4 60 12 (ps (format SY *Scl)))
(for X SX
(window (+ 6 (*/ (dec X) DX SX)) (+ 24 DY) 30 12
(ps (format (dec X)) 0) ) ) )
(page) ) ) )
 
(plot "plot.ps" 300 200 (2.7 2.8 31.4 38.1 58.0 76.2 100.5 130.0 149.3 180.0))
(call 'display "plot.ps")

[edit] PostScript

 
/x [0 1 2 3 4 5 6 7 8 9] def
/y [2.7 2.8 31.4 38.1 58.0 76.2 100.5 130.0 149.3 180.0] def
/i 1 def
 
newpath
x 0 get y 0 get moveto
x length 1 sub{
x i get y i get lineto
/i i 1 add def
}repeat
stroke
 

[edit] PureBasic

Structure PlotData
x.i
y.f
EndStructure
 
Global i, x, y.f, max_x, max_y, min_x=#MAXLONG, min_y=Infinity()
Global count=(?serie_y-?serie_x)/SizeOf(Integer)-1
Global Dim MyData.PlotData(count)
 
Restore serie_x
For i=0 To count
Read.i x
MyData(i)\x=x
If x>max_x: max_x=x: EndIf
If x<min_x: min_x=x: EndIf
Next
Restore serie_y
For i=0 To count
Read.f y
MyData(i)\y=y
If y>max_y: max_y=y: EndIf
If y<min_y: min_y=y: EndIf
Next
 
Procedure UpdatePlot(Win, w, h)
If w>20 And h>20
SetWindowTitle(win,"PureBasic Plot "+Str(w)+"x"+Str(h))
Protected x, y, i, yf.f, xf.f, img
Protected x0=20, y0=h-20, amounts=ArraySize(MyData())
Protected x1,x2,y1,y2
yf=(h-20)/max_y*0.99
xf=(w-20)/max_x*0.99
CreateImage(0,w,h)
Define OutputID=ImageOutput(0)
StartDrawing(OutputID)
DrawingMode(#PB_2DDrawing_Transparent)
LineXY(20,h-20,w,h-20,$FFFFFF)
LineXY(20,h-20,20,0,$FFFFFF)
For i=0 To amounts
;- Draw grid
x1=20: x2=w
y1=(h-20)-max_y*i/amounts*yf
y2=y1
LineXY(x1,y1,x2,y2,$467E3E)
; Y-scale
DrawText(1,y1-5,RSet(StrD(i/10*max_y,1),5))
x1=20+max_x*i/amounts*xf
x2=x1: y1=(h-20): y2=0
; X-Scale
LineXY(x1,y1,x2,y2,$467E3E)
If i: DrawText(x1-5,y1+2,Str(i)): EndIf
;- Draw curve
x=20+MyData(i)\x*xf
y=(h-20)-MyData(i)\y*yf
LineXY(x0,y0,x,y,$0133EE)
x0=x: y0=y
Next
StopDrawing()
ImageGadget(0,0,0,w,h,ImageID(0))
EndIf
EndProcedure
 
Define Flags=#PB_Window_SystemMenu|#PB_Window_SizeGadget
Define Win=OpenWindow(#PB_Any,0,0,600,400,"",Flags)
If Win
SmartWindowRefresh(Win,1)
UpdatePlot(Win, WindowWidth(Win), WindowHeight(win))
Repeat
Define Event =WaitWindowEvent()
Select Event
Case #PB_Event_SizeWindow
UpdatePlot(Win, WindowWidth(Win), WindowHeight(win))
EndSelect
Until Event=#PB_Event_CloseWindow
; Save the plot if the user wants to
Flags=MessageRequester("Question","Save it?",#PB_MessageRequester_YesNo)
If Flags=#PB_MessageRequester_Yes
Define file$=SaveFileRequester("Save as","PB.png","PNG (*.png)|*.png",0)
UsePNGImageEncoder()
SaveImage(0,file$,#PB_ImagePlugin_PNG)
EndIf
EndIf
 
DataSection
serie_x: Data.i 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
serie_y: Data.f 2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0
EndDataSection

File:PureBasic PlotData.png

[edit] Python

Library: matplotlib
matplotlib plot of x,y arrays
>>> x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> y = [2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0]
 
>>> import pylab
>>> pylab.plot(x, y, 'bo')
>>> pylab.savefig('qsort-range-10-9.png')

qsort-range-10-9.png (23 KiB)

[edit] R

R has several different plotting paradigms. First we define the data.

x <- c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
y <- c(2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0)

[edit] Base graphics

plot(x,y)

[edit] Lattice/grid graphics

Library: lattice

library(lattice)
xyplot(y~x)

[edit] Grammar of graphics

Library: ggplot2

library(ggplot2)
qplot(x,y)

[edit] Tcl

Library: Tk Library: Img

This solution does not use existing plotting packages, but constructs the graphics from bare-metal Tk code.

package require Tk
 
# The actual plotting engine
proc plotxy {canvas xs ys} {
global xfac yfac
set maxx [tcl::mathfunc::max {*}$xs]
set maxy [tcl::mathfunc::max {*}$ys]
set xfac [expr {[winfo width $canvas] * 0.8/$maxx}]
set yfac [expr {[winfo height $canvas] * 0.8/$maxy}]
scale $canvas x 0 $maxx $xfac
scale $canvas y 0 $maxy $yfac
foreach x $xs y $ys {
dot $canvas [expr {$x*$xfac}] [expr {$y*$yfac}] -fill red
}
}
# Rescales the contents of the given canvas
proc scale {canvas direction from to fac} {
set f [expr {$from*$fac}]
set t [expr {$to*$fac}]
switch -- $direction {
x {
set f [expr {$from * $fac}]
set t [expr {$to * $fac}]
$canvas create line $f 0 $t 0
$canvas create text $f 0 -anchor nw -text $from
$canvas create text $t 0 -anchor n -text $to
 
}
y {
set f [expr {$from * -$fac}]
set t [expr {$to * -$fac}]
$canvas create line 0 $f 0 $t
$canvas create text 0 $f -anchor se -text $from
$canvas create text 0 $t -anchor e -text $to
}
}
}
# Helper to make points, which are otherwise not a native item type
proc dot {canvas x y args} {
set id [$canvas create oval [expr {$x-3}] [expr {-$y-3}] \
[expr {$x+3}] [expr {-$y+3}]]
$canvas itemconfigure $id {*}$args
}
 
pack [canvas .c -background white]
update
set xs {0 1 2 3 4 5 6 7 8 9}
set ys {2.7 2.8 31.4 38.1 58.0 76.2 100.5 130.0 149.3 180.0}
plotxy .c $xs $ys
.c config -scrollregion [.c bbox all]
.c move all 20 20
 
# Save image (this is the only part that requires an external library)
package require Img
set im [image create photo -data .c]
$im write plotxy.png -format PNG

Of course, if we were generating an encapsulated postscript version, we would be able to do that directly.

[edit] TI-89 BASIC

TI-89 screenshot
FnOff
PlotsOff
NewPlot 1, 1, x, y
ZoomData

[edit] Ursala

Ursala doesn't plot anything directly, but has libraries to generate LaTeX code for 2D and 3D graphics. The output file has to be run through LaTeX or included into a LaTeX document. Here's the way to do it just as a quick check (all default settings and dots connected with straight lines).

#import std
#import flo
#import fit
#import plo
 
x = <0., 1., 2., 3., 4., 5., 6., 7., 8., 9.>
y = <2.7, 2.8, 31.4, 38.1, 58.0, 76.2, 100.5, 130.0, 149.3, 180.0>
 
#output dot'tex' latex_document+ plot
 
main = visualization[curves: <curve[points: ~&p/x y]>]

(output)

Here's one way you might do it if you were interested in publication quality graphics. The dots are connected with a cubic spline interpolating function sampled at 200 points, and the axes are nicely labeled.

main =
 
visualization[
abscissa: axis[
variable: 'problem size',
hats: printf/*'%0.0f' ari10/0. 9.],
ordinates: ~&iNC axis[
variable: 'execution time ($\mu$s)',
hats: printf/*'%0.1f' ari6/0. 180.],
curves: <
curve[
points: ^(~&,chord_fit0@p/x y)* ari200/0. 9.,
attributes: {'linecolor': 'lightgray'}],
curve[
scattered: true,
points: ~&p/x y,
attributes: {'linecolor': 'black'}]>]

(output)

Personal tools
Support