Grafické zobrazování dat

Antonín Slavík
MFF UK

ListPlot a příbuzné funkce

ListPlot

deficit={{1998,29.3},{1999,29.6},{2000,46.1},{2001,67.7},{2002,45.7},{2003,109.1},{2004,93.5},{2005,56.4},{2006,97.3},{2007,66.4},{2008,19.4},{2009,192.2},{2010,156.4},{2011,142.8},{2012,101},{2013,81.3}};

ListPlot[deficit]

ListPlot[deficit,Filling->Axis,FillingStyle->Directive[Thick,Gray],PlotRange->{0,All},PlotStyle->{Blue,PointSize[Large]},Ticks->{Range[1996,2013,2],Automatic},BaseStyle->{FontFamily->"Arial",FontSize->12},PlotLabel->"Deficit státního rozpočtu ČR (miliardy Kč)\n"]

DateListPlot

Průměrné denní teploty v Praze v březnu 2015:

teploty=WeatherData["Prague","Temperature",{{2015,3,1},{2015,3,31},"Day"}]

DateListPlot[teploty]

DateListPlot[teploty,PlotStyle->Red,BaseStyle->{FontFamily->"Arial",FontSize->12},PlotRange->All,DateTicksFormat->{"Day","/","Month"},PlotRangePadding->None,FrameTicks->{{Automatic,None},{Automatic,None}},PlotLabel->"Průměrné denní teploty v Praze v březnu 2015"]

Další funkce

ListLinePlot, ListLogPlot, ListPlot3D, ... (viz dokumentaci)

BarChart a BarChart3D

BarChart[{(Subscript[y, 1]),(Subscript[y, 2]),…}] sestrojí sloupcový diagram, kde výšky sloupců jsou dány hodnotami (Subscript[y, i]).

beerCountries={"Česká republika","Německo","Rakousko","Estonsko","Polsko","Irsko","Rumunsko","Litva","Chorvatsko","Belgie"};
beerConsumption={143,110,108,104,100,93,90,89,82,81};
(* údaje za rok 2014, zdroj: The Telegraph, http://www.telegraph.co.uk/finance/newsbysector/retailandconsumer/leisure/11237013/Mapped-Beer-sales-around-the-world-who-drinks-the-most.html *)

BarChart[beerConsumption]

BarChart[beerConsumption,ChartLegends->beerCountries,PlotLabel->"Státy s největší spotřebou piva na osobu (litry za rok)",ChartStyle->"ThermometerColors",BaseStyle->{FontFamily->"Arial",FontSize->12},BarSpacing->0]

Specifikace barev

Barvy zadány seznamem:

BarChart[{1,2,3,2},ChartStyle->{Brown,Red,Orange,Yellow}]

Barvy určeny výškou a obarvovací funkcí:

BarChart[Table[Binomial[8,k],{k,0,8}],ColorFunction->(Hue[1/2+#/2]&)]

Rozdíl mezi ChartStyle a ColorFunction:

BarChart[Table[Binomial[8,k],{k,0,8}],ChartStyle->"SunsetColors"]

BarChart[Table[Binomial[8,k],{k,0,8}],ColorFunction->"SunsetColors"]

Placed

Konstrukce Placed[výraz,pozice] vyhodnotí výraz a umístí jej na zadanou pozici; ta je obvykle určena symbolickými názvy jako např. Top, Bottom, Left, Right, Center, apod.

BarChart[{1,2,3,2},ChartStyle->{Brown,Red,Orange,Yellow},ChartLegends->Placed[{"A","B","C","D"},Bottom]]

Tooltip

Konstrukce Tooltip[výraz,text] vrátí vyhodnocený výraz. Při umístění kurzoru myši nad výraz se zobrazí zadaný text.

Tooltip[10!,"Toto je hodnota 10!"]

Plot[{Tooltip[Sin[x],"Toto je graf funkce sinus."],Tooltip[Cos[x],"Toto je graf funkce kosinus."]},{x,0,2Pi}]

BarChart[MapThread[Tooltip[#1,StringForm["``: `` litrů na osobu a rok",#2,Round@#1]]&,{beerConsumption,beerCountries}],ChartLegends->beerCountries,PlotLabel->"Státy s největší spotřebou piva na osobu (litry za rok)",ChartStyle->"ThermometerColors",BaseStyle->{FontFamily->"Arial",FontSize->12},BarSpacing->0]

Data ve více skupinách

staty={"Česká republika","Polsko","Slovensko","Maďarsko"};
roky={"2009","2010","2011","2012","2013"};
inflace={{0.6,4.0,0.9,4.0},{1.2,2.7,0.7,4.7},{2.1,3.9,4.1,3.9},{3.5,3.7,3.7,5.7},{ 1.4,0.8,1.5,1.7}}; (* zdroj: Eurostat *)

BarChart[inflace,ChartLegends->staty,BarSpacing->{0,1},ChartLabels->{roky,None},Axes->{True,False},PlotLabel->"Inflace ve středoevropských zemích",BaseStyle->{FontFamily->"Arial",FontSize->12},ChartStyle->{Brown,Red,Orange,Yellow}]

Řazení podle států:

BarChart[Transpose[inflace],ChartLegends->roky,BarSpacing->{0,1},ChartLabels->{staty,None},Axes->{True,False},PlotLabel->"Inflace ve středoevropských zemích",BaseStyle->{FontFamily->"Arial",FontSize->12},ChartStyle->{Red,Blue,Yellow,Green,Orange}]

Další volby

Manipulate[BarChart[inflace,ChartLegends->staty,BarSpacing->{0,1},ChartLabels->{roky,None},Axes->{True,False},PlotLabel->"Inflace ve středoevropských zemích",BaseStyle->{FontFamily->"Arial",FontSize->12},ChartStyle->{Brown,Red,Orange,Yellow},BarOrigin->barOrigin,ChartElementFunction->f,LabelingFunction->labelfn,ChartLayout->layout],{{barOrigin,Bottom,"BarOrigin"},{Top,Bottom,Left,Right}},{{f,"Rectangle","ChartElementFunction"},ChartElementData["BarChart"]},{{labelfn,Automatic,"LabelingFunction"},{Automatic,None,Bottom,Center,Top,Below,Above,Before,After}},{{layout,"Grouped","ChartLayout"},{"Grouped","Stacked","Percentile","Stepped"}}]

K snadnému výběru ChartElementFunction lze použít paletu Chart Element Schemes.

BarChart3D

BarChart3D vyrábí trojrozměrné sloupcové diagramy, používá se stejně jako BarChart.

BarChart3D[beerConsumption,ChartLegends->beerCountries,PlotLabel->"Státy s největší spotřebou piva na osobu (litry za rok)",ChartStyle->"ThermometerColors",BaseStyle->{FontFamily->"Arial",FontSize->12},BarSpacing->0]

BarChart3D[inflace,ChartLegends->staty,BarSpacing->{0,1},ChartLabels->{roky,None},PlotLabel->"Inflace ve středoevropských zemích",BaseStyle->{FontFamily->"Arial",FontSize->12},ChartStyle->{Brown,Red,Orange,Yellow}]

Manipulate[BarChart3D[inflace,ChartLegends->staty,BarSpacing->{0,1},ChartLabels->{roky,None},PlotLabel->"Inflace ve středoevropských zemích",BaseStyle->{FontFamily->"Arial",FontSize->12},ChartLayout->layout,ChartStyle->{Brown,Red,Orange,Yellow},BarOrigin->barOrigin,ChartElementFunction->f,LabelingFunction->labelfn],{{barOrigin,Bottom,"BarOrigin"},{Top,Bottom,Left,Right}},{{f,"FadingCube","ChartElementFunction"},ChartElementData["BarChart3D"]},{{layout,"Grouped","ChartLayout"},{"Grouped","Stacked","Percentile","Stepped"}},{{labelfn,Automatic,"LabelingFunction"},{Automatic,None,Bottom,Center,Top,Below,Above,Before,After}}]

PairedBarChart

PairedBarChart[{1,3,5},{2,4,6}]

Příklad: Věkové složení obyvatel ČR k 31. 12. 2013 (zdroj: ČSÚ)

soubor1=Import["http://www.karlin.mff.cuni.cz/~slavik/pokrocili_ls_2014_15/cr_muzi.xlsx"]; 
soubor2=Import["http://www.karlin.mff.cuni.cz/~slavik/pokrocili_ls_2014_15/cr_zeny.xlsx"];

muzi=Table[soubor1[[1,i,2]],{i,7,107}]

zeny=Table[soubor2[[1,i,2]],{i,7,107}]

Celkový počet obyvatel (kontrola):

Total[zeny]+Total[muzi]

PairedBarChart[muzi,zeny,ImageSize->{Automatic,500},AspectRatio->1]

Úprava vzhledu:

PairedBarChart[muzi,zeny,ImageSize->{Automatic,600},AspectRatio->1,ChartStyle->{{Red,Lighter@Blue},None,None},ChartLegends->{{"Muži","Ženy"},None,None},ChartLabels->(Map[If[Mod[#,5]==0,ToString[#],""]&,Range[0,99]]~Join~{"100+"})]

PieChart a PieChart3D

PieChart[{(Subscript[y, 1]),(Subscript[y, 2]),…}] sestrojí kruhový (koláčový) diagram, kde velikosti úhlů výsečí jsou úměrné hodnotám (Subscript[y, i]).

browserShares={46.26,20.31,17.5,10.81,1.47,3.65};
legend={"Chrome","Internet Explorer","Firefox","Safari","Opera","Ostatní"};
txt="Podíl webových prohlížečů v srpnu 2014\n (desktopy, tablety, konzole)";
(* zdroj: StatCounter, http://gs.statcounter.com/#browser-ww-monthly-201408-201408-bar *)

PieChart[browserShares,ChartLegends->legend,ChartStyle->"BrightBands",PlotLabel->txt,BaseStyle->{FontFamily->"Arial",FontSize->12}]

Poznámka: Kliknutím myší lze vysunout výseč.

Mezikruží se zadaným vnitřním poloměrem:

PieChart[browserShares,ChartLegends->legend,ChartStyle->"BrightBands",SectorOrigin->{Automatic,1},PlotLabel->txt,BaseStyle->{FontFamily->"Arial",FontSize->12}]

Manipulate[PieChart[browserShares,PlotLabel->txt,BaseStyle->{FontFamily->"Arial",FontSize->12},ChartLegends->legend,ChartStyle->"BrightBands",ChartElementFunction->f,LabelingFunction->labelfn,SectorOrigin->{{theta,"Clockwise"},radius}],{{f,"Sector","ChartElementFunction"},ChartElementData["PieChart"]},{{labelfn,Automatic,"LabelingFunction"},{Automatic,None,"RadialInner","RadialCenter","RadialOuter","RadialInside","RadialOutside","RadialEdge","RadialCallout","VerticalCallout"}},{theta,0,2Pi},{{radius,1},0,2}]

PieChart3D vyrábí trojrozměrný diagram, používá se stejně jako PieChart.

PieChart3D[browserShares,PlotLabel->txt,BaseStyle->{FontFamily->"Arial",FontSize->12},ChartLegends->legend,ChartStyle->"BrightBands"]

PieChart3D[browserShares,PlotLabel->txt,BaseStyle->{FontFamily->"Arial",FontSize->12},ChartLegends->legend,ChartStyle->"BrightBands",SectorOrigin->{Automatic,1}]

Manipulate[PieChart3D[browserShares,PlotLabel->txt,SectorOrigin->{{theta,"Counterclockwise"},radius},BaseStyle->{FontFamily->"Arial",FontSize->12},ChartStyle->"BrightBands",ChartLegends->legend,SectorOrigin->{Automatic,1},ChartElementFunction->f,LabelingFunction->labelfn],{{f,"CylindricalSector3D","ChartElementFunction"},ChartElementData["PieChart3D"]},{{labelfn,Automatic,"LabelingFunction"},{Automatic,None,"RadialInner","RadialCenter","RadialOuter","RadialInside","RadialOutside","RadialEdge","RadialCallout","VerticalCallout"}},{theta,0,2Pi},{{radius,1},0,2}]

Více skupin dat:

PieChart3D[{{1,2,3,2},{3,4,2,1},{1,2,2,1}},ChartLegends->{"A","B","C","D"}]

Další typy grafů

RectangleChart

RectangleChart[{{(Subscript[x, 1]),(Subscript[y, 1])},{(Subscript[x, 1]),(Subscript[y, 2])},…}] sestrojí obdélníkový diagram, kde šířky obdélníků jsou úměrné hodnotám (Subscript[x, i]) a jejich výšky hodnotám (Subscript[y, i]).

Příklad: Hrubý domácí produkt a počet obyvatel států G8.

countries={"Canada","France","Germany","Italy","Japan","Russia","UnitedKingdom","UnitedStates"};

gdpPerCapita=Map[CountryData[#,"GDPPerCapita"]&,countries]

population=Map[CountryData[#,"Population"]&,countries]

GDPData=Transpose[{population,gdpPerCapita}]

RectangleChart[GDPData,BaseStyle->{FontFamily->"Arial",FontSize->14},ChartStyle->"TemperatureMap",ChartLabels->Placed[countries,Below,Rotate[#,Pi/2]&],PlotLabel->"Visualizing GDP Per Capita\n",ChartLegends->Map[Row[{"$",#}]&,gdpPerCapita],LabelingFunction->(Placed[#,Tooltip,Column[{Row[{"Population (x-axis) : ",First@#}],Row[{"GDP Per Capita (y-axis) : $",Last@#}],Row[{"GDP : $",Last@#*First@#}]},Alignment->{Left,Bottom}]&]&)]

SectorChart

SectorChart[{{(Subscript[x, 1]),(Subscript[y, 1])},{(Subscript[x, 1]),(Subscript[y, 2])},…}] sestrojí výsečový diagram, kde velikost úhlů výsečí jsou úměrné hodnotám (Subscript[x, i]) a jejich poloměry hodnotám (Subscript[y, i]).

dollarForm[a_Real]:=Row[{"$",NumberForm[a,{10,2},NumberPadding->{"","0"}]}];

SectorChart[GDPData,SectorOrigin->{Automatic,11000},BaseStyle->{FontFamily->"Arial",FontSize->14},ChartStyle->"TemperatureMap",ChartLabels->Placed[countries,"RadialCallout",#1&],Epilog->Text["GDP"],PlotLabel->"Visualizing GDP Per Capita",PlotRange->All,ChartLegends->Placed[gdpPerCapita*population,Right,#1&],LabelingFunction->(Placed[#1,Tooltip,Column[{Row[{"Population (Angle): ",First[#1]}],Row[{"GDP Per Capita (Radius): ",Last[#1]}],Row[{"GDP : ",dollarForm[First[#1] Last[#1]]}]},Alignment->{Left,Bottom}]&]&)]

RectangleChart3D

RectangleChart3D[{{(Subscript[x, 1]),(Subscript[y, 1]),(Subscript[z, 1])},{(Subscript[x, 2]),(Subscript[y, 2]),(Subscript[z, 2])},…}] sestrojí diagram složený z kvádrů se šířkami (Subscript[x, i]), hloubkami (Subscript[y, i]) a výškami (Subscript[z, i]).

countries={"Algeria","Argentina","Brazil","Chile","Colombia","Egypt","India","Indonesia","Iran","Jamaica","Kenya","Malaysia","Mexico","Nigeria","Peru","Senegal","SriLanka","Venezuela","Zimbabwe"};
properties={"FemaleAdultPopulation","TotalFertilityRate","FemaleLifeExpectancy"};
femaleData=Table[CountryData[c,p],{c,countries},{p,properties}]

RectangleChart3D[femaleData,ChartLabels->Placed[countries,Tooltip],BarSpacing->{0,0},ViewPoint->{3,-9,4},AxesLabel->properties,ChartStyle->24,BaseStyle->{FontFamily->"Arial",FontSize->12},ImageSize->Large]

BubbleChart

BubbleChart[{{(Subscript[x, 1]),(Subscript[y, 1]),(Subscript[z, 1])},{(Subscript[x, 2]),(Subscript[y, 2]),(Subscript[z, 2])},…}] sestrojí bublinkový diagram, kde středy bublinek jsou určeny hodnotami {(Subscript[x, i]),(Subscript[y, i])} a jejich obsahy jsou úměrné hodnotám (Subscript[z, i]).

countries=CountryData["Africa"];
properties={"PovertyFraction","GDPPerCapita","Population"};
data={#1,Log@QuantityMagnitude@#2,#3}&@@@Table[CountryData[c,p],{c,countries},{p,properties}];

labeler[v_,{r_,c_},___]:=Placed[Grid[{{Style[countries[[c]],Bold,12],SpanFromLeft},{"Poverty",Row[{Round[100v[[1]]],"%"}]},{"GDP Per Capita",Row[{"$",Round[Exp[v[[2]]]]}]},{"Population",Row[{NumberForm[v[[3]] 10.^-6,{4,2}]," million"}]}},Alignment->Left],Tooltip]

BubbleChart[data,ChartStyle->24,LabelingFunction->labeler,FrameLabel->{"Poverty Fraction","Log GDP Per Capita"}]

Ostatní typy grafů

BubbleChart3D, SectorChart3D – viz dokumentaci.

Histogram a Histogram3D

Normální čísla

RealDigits vrací seznam cifer daného čísla ve zvolené soustavě:

RealDigits[Pi,10,6]

Seznam prvních 10 000 cifer čísla π:

piDigits=First[RealDigits[Pi,10,10^4]];

Tally počítá četnosti prvků v zadaném seznamu:

Tally[piDigits]

Histogram zobrazuje četnosti hodnot v daném seznamu pomocí sloupcového diagramu.

Histogram[piDigits]

Histogram[piDigits,ChartStyle->"TemperatureMap",LabelingFunction->Above,Axes->{True,False},Ticks->None,ChartLegends->Range[0,9]]

Jaké jsou četnosti dvojic po sobě jdoucích cifer? K získání dvojic použijeme Partition.

Partition[{a,b,c,d,e,f},2,1]

dvojice=Partition[piDigits,2,1];

Sort[Tally[dvojice]]

Histogram3D zobrazuje četnosti dvojic hodnot v daném seznamu:

Histogram3D[dvojice]

Hypotéza: Nechť w je libovolná k-tice cifer a nechť P(w,n) je počet výskytů této k-tice cifer na prvních n místech desítkového zápisu čísla π. Pak (lim_(n→∞))((P(w,n))/n)=(10^(-k)).

Toto je otevřený problém. O číslech splňujících zadanou podmínku říkáme, že jsou normální v desítkové soustavě. Číslo je normální, pokud je normální v soustavě o libovolném základu b∈{2,3,4, …}.

Zdá se, že i mnoho dalších čísel je normálních:

Histogram[First[RealDigits[E,10,10^4]],ChartStyle->"TemperatureMap",LabelingFunction->Above,Axes->{True,False},Ticks->None,ChartLegends->Range[0,9]]

Histogram3D[Partition[First[RealDigits[E,10,10^4]],2,1]]

Histogram[First[RealDigits[Sqrt[2],10,10^4]],ChartStyle->"TemperatureMap",LabelingFunction->Above,Axes->{True,False},Ticks->None,ChartLegends->Range[0,9]]

Histogram3D[Partition[First[RealDigits[Sqrt[2],10,10^4]],2,1]]

Některé známé výsledky:

E. Borel (1909): Pojem normálního čísla, skoro všechna čísla jsou normální (Lebesgueova míra nenormálních je 0, i když je jich nespočetně)

W. Sierpinski (1917): První konkrétní příklad normálního čísla

D. G. Champernowne (1933): 0.12345678910111213... je normální

Inset

Inset[obj,pos,opos,size] reprezentuje grafiku, která vznikne transformací zadaného objektu obj. Ten je umístěn tak, že bod na pozici opos v souřadnicovém systému objektu splyne s bodem na pozici pos v souřadnicovém systému grafiky, do které je objekt vkládán; velikost objektu je nastavena na size.

g=Graphics[{Blue,Rectangle[{0,0},{1,1}]},PlotRangePadding->None];
Graphics[{Yellow,Rectangle[{-1,-1},{1,1}],Inset[g,{0,0},{1,1},{1/2,1/2}]},PlotRange->{{-2,2},{-2,2}},Frame->True]

Místo x-ové souřadnice lze psát Left, Center nebo Right, místo y-ové souřadnice může být Top, Center, Bottom.

Parametry opos a size není potřeba uvádět (výchozí hodnota opos je Center, výchozí hodnota size je přirozená velikost obrázku). Je-li jedna složka size nastavena na Automatic, bude dopočtena se zachováním poměru stran.

Vložení bitmapového obrázku do grafiky

pivo=;

BarChart[MapThread[Tooltip[#1,StringForm["``: `` litrů na osobu a rok",#2,Round@#1]]&,{beerConsumption,beerCountries}],ChartLegends->beerCountries,Axes->{False,True},PlotLabel->"Státy s největší spotřebou piva na osobu (litry za rok)\n",ChartStyle->"ThermometerColors",BaseStyle->{FontFamily->"Arial",FontSize->12},BarSpacing->0,Prolog->Inset[pivo,{Center,Top},{Center,Top}]]

Vkládání legend

Příkazy jako Plot, ParametricPlot, ListPlot apod. mají volbu PlotLegends pro vkládání popisků.

Plot[{Tan[x],ArcTan[x]},{x,-Pi/2,Pi/2},AspectRatio->1,PlotStyle->{{Thick,Red},{Thick,Blue}}]

Automaticky vyrobená legenda:

Plot[{Tan[x],ArcTan[x]},{x,-Pi/2,Pi/2},AspectRatio->1,PlotStyle->{{Thick,Red},{Thick,Blue}},PlotLegends->"Expressions"]

Ručně vyrobená legenda:

legend=Framed[LineLegend[{Red,Blue},{"tg x","arctg x"},LabelStyle->{FontFamily->"Arial",FontSize->14,FontSlant->Italic}]]

Plot[{Tan[x],ArcTan[x]},{x,-Pi/2,Pi/2},AspectRatio->1,PlotStyle->{{Thick,Red},{Thick,Blue}},BaseStyle->{FontFamily->"Arial",FontSize->12},PlotLegends->Placed[legend,{Left,Top}]]

Místo LineLegend je k dispozici též PointLegend nebo SwatchLegend.

U obrázků vytvořených pomocí Graphics je potřeba použít konstrukci Legended[grafika, legenda].

Diagram Florence Nightingalové

Florence Nightingale (1820–1910), anglická statistička, spisovatelka a dobrovolná zdravotní sestra v krymské válce. Je autorkou následujícího diagramu:

Florence Nightingale: Notes on Matters Affecting the Health, Efficiency, and Hospital Administration of the British Army (1858).
Diagram znázorňuje počty a příčiny úmrtí britských vojáků v krymské válce (1854–1855). Obsahy ploch jsou úměrné počtům zemřelých vojáků.

Následující údaje jsou převzaty ze stránky http://understandinguncertainty.org/node/214.

mortalityData={{0,(5/8571),(1/8571)},{0,(9/23333),(12/23333)},{0,(6/28333),(11/28333)},{0,(23/28722),(359/28722)},{(1/30246),(5/5041),(138/5041)},{(81/30290),(7/3029),(394/15145)},{(132/30643),(128/30643),(503/30643)},{(41/4248),(53/14868),(211/7434)},{(114/32779),(131/32779),(1725/32779)},{(83/32393),(324/32393),(2761/32393)},{(6/4417),(361/30919),(2120/30919)},{(32/30107),(172/30107),(1205/30107)}};

colors={Red,Orange,Darker[Green]};
months={"April 1854","May 1854","June 1854","July 1854","August 1854","September 1854","October 1854","November 1854","December 1854","January 1855","February 1855","March 1855"};
f[r_,theta_]:=(Sqrt[r]) {Cos[theta],Sin[theta]}
angles=π-Range[0,2 π,((2 π)/12)];
gr=Graphics[MapIndexed[{Line[{{0,0},f[#1[[3]],angles[[First[#2]]]]}],Line[{{0,0},f[#1[[3]],angles[[First[#2]+1]]]}],Table[{EdgeForm[{Black}],colors[[i]],Tooltip[Disk[{0,0},(Sqrt[#1[[i]]]),{angles[[First[#2]+1]],angles[[First[#2]]]}],months[[First[#2]]]]},{i,3,1,-1}]}&,mortalityData]]

legend=SwatchLegend[colors,{"Death from wounds in battle","Death from disease","Death from other causes"},LabelStyle->{FontFamily->"Arial",FontSize->14,FontSlant->Italic}]

Framed[Legended[gr,Placed[legend,{Left,Top}]]]