Gnuplot, pie chart, placing labels on left, can

2019-05-18 01:34发布

问题:

I need to make some pie charts using Gnuplot. I used the code I found here, on SO. My data file looks like this:

Województwo Suma
Dolnośląskie    3.6 
Kujawsko-Pomorskie  7.5
Lubelskie   4.7
Lubuskie    3.3
Łódzkie 8.1
Małopolskie 6.9 
Mazowieckie 12.5
Opolskie    2.6
Podkarpackie    6    
Podlaskie   3.4
Pomorskie   8
Śląskie 14

And my Gnuplot script:

#!/usr/bin/gnuplot

set encoding utf8 
set datafile separator "\t"
set termoption enhanced

set terminal epscairo enhanced color dashed rounded size 8.5, 5.5
set output '2008-2015procent_pie.eps'

stats '2008-2015procent_pie.csv' u 2 noout      # get STATS_sum (sum of column 2)

ang(x)=x*360.0/STATS_sum        # get angle (grades)
perc(x)=x*100.0/STATS_sum       # get percentage

set size square                 # square canvas
set xrange [-1:1.5]
set yrange [-1.25:1.25]
set style fill solid 1

unset border            # remove axis
unset tics                # remove tics on axis
unset colorbox            # remove palette colorbox 
unset key                 # remove titles

Ai = 0.0; Bi = 0.0;             # init angle
mid = 0.0;                      # mid angle
i = 0; j = 0;                   # color
yi  = 0.0; yi2 = 0.0;           # label position

set palette defined (1 1 0.788 0.055, 2 0.090 0.161 0.659) 

plot for [i=1:STATS_records] '2008-2015procent_pie.csv' u (0):(0):(1):(Ai):(Ai=Ai+ang($2)):(i) every ::i::i with circle linecolor palette,\
     '2008-2015procent_pie.csv' u (mid=(Ai+ang($2)), Ai=2*mid-Ai, mid=mid*pi/360.0, -0.5*cos(mid)):(-0.5*sin(mid)):(sprintf('%.1f\%', $2, perc($2))) ever\
y ::1 w labels center font ',10',\
     for [i=1:STATS_records] '2008-2015procent_pie.csv' u (1.45):(i*0.25):1 every ::i::i with labels left,\
     for [i=1:STATS_records] '+' u (1.3):(i*0.25):(i) pt 5 ps 4 lc palette

I have 2 problems with this script:

  1. I don't see all labels, is it possible to move the labels somehow that I could see them all?
  2. Colours: here, on my pie chart I have basically only 2 colours - yellow and blue. How to make it so I could have a variety of colours, different colour for different value?

My chart looks like this now:

Thank you.

-----------------------------------------------------------------------------------------------------------------------------------EDIT -----------------------------------------------------------------------------------------------------------------------------------

I changed a bit my script, as suggested by @RolandSmith, also, I modified a little my data file, Now it looks like this:

Województwo Suma
Dolnośląskie    3.6 
Kujawsko-Pomorskie  7.5
Lubelskie   4.7
Lubuskie    3.3
Łódzkie 8.1
Małopolskie 6.9 
Mazowieckie 12.5
Opolskie    2.6
Podkarpackie    6    
Podlaskie   3.4
Pomorskie   8
Śląskie 14
Świętokrzyskie  2.8  
Warmińsko-Mazurskie 4    
Wielkopolskie   7.9
Zachodniopomorskie  4.6

And the modified script:

#!/usr/bin/gnuplot

set encoding utf8 
set datafile separator "\t"
set termoption enhanced

set terminal epscairo enhanced color dashed rounded size 8.5, 5.5
set output '2008-2015procent_pie.eps'

stats '2008-2015procent_pie.csv' u 2 noout      # get STATS_sum (sum of column 2)

ang(x)=x*360.0/STATS_sum        # get angle (grades)
perc(x)=x*100.0/STATS_sum       # get percentage

set size square                 # square canvas
set xrange [-1:1.5]
set yrange [-1.25:1.25]
set style fill solid 1

unset border            # remove axis
unset tics                # remove tics on axis
unset colorbox            # remove palette colorbox 
unset key                 # remove titles

Ai = 0.0; Bi = 0.0;             # init angle
mid = 0.0;                      # mid angle
i = 0; j = 0;                   # color
yi  = 0.0; yi2 = 0.0;           # label position

set palette rgb 33,13,10;

plot for [i=1:STATS_records] '2008-2015procent_pie.csv' u (0):(0):(1):(Ai):(Ai=Ai+ang($2)):(i) every ::i::i with circle linecolor palette,\
     '2008-2015procent_pie.csv' u (mid=(Ai+ang($2)), Ai=2*mid-Ai, mid=mid*pi/360.0, -0.5*cos(mid)):(-0.5*sin(mid)):(sprintf('%.1f\%', $2, perc($2))) every ::1 w labels center font ',10',\
     for [i=1:STATS_records] '2008-2015procent_pie.csv' u (1.45):(i*0.25)-1.9:1 every ::i::i with labels left,\
     for [i=1:STATS_records] '+' u (1.3):(i*0.25)-1.9:(i) pt 5 ps 4 lc palette

Now the problem is with labels - I still can't see all of them. There should be 16 labels, as you can see from the CSV file. I tried to change the page size, with no success. Thank you for help.

Current pie:

回答1:

  1. To move the labels in the pie-chart inwards or outwards, change the "-0.5" in front of the sin and cos. To move the labels and the color-squares, change (i*0.25) to (i*0.25)-1.2 in the third and fourth plot.

    Update: Change (i*0.25) to e.g. (i*0.18) to make the distance between the labels smaller. And change ps 4 to e.g. ps 3 to make the squares smaller.

  2. Define a larger palete. Your current one only has two entries. Get one with as least as much colors as you have entries. You could use colorbrewer to generate palette colors.

Some other points.

  • While this is really very clever, you're probably pushing gnuplot way beyond what it was intended. Consider using another tool like e.g. Python's matplotlib.

  • Your data doesn't add up to 100, but only to 80.6. So you should scale your figure properly using the ang and perc functions. I can't put my finger on it, but it doesn't look right.

  • In the sprintf, you should only use the percentage:sprintf('%.1f\%', perc($2))