Hintergrund
Angenommen, Sie haben Daten wie diese im Datenabschnitt von datavisualization
, die auch aus einer Datei stammen könnten,
date,birds
30/10/2023,1200
02/10/2023,1229
...
oder
species,birds
spec4,1200
spec1,1229
...
\datavisualization
bietet zwei Visualisierungen, scientific axes
und school book axes
, die beide xy-Daten erfordern.
Frage
Es ist keine große Sache, die Text-X-Daten durch einen Zähler zu ersetzen und so eine einfache Ordinal-Skala einzuführen. Aber wie kann man die ursprünglichen X-Daten beibehalten oder darauf zugreifen UND sie als Beschriftungen auf der X-Achse anbringen, statt 1,2,...?
Versuche
Der folgende Code bietet \pgfdeclaredataformat{ordinalX}
, das die X-Daten durch einen einfachen Zähler NX ersetzt.
Ich weiß, ichkönnteeine Liste, z.B. via ticks={major at={1 as spec4,...}}
, per Hand in die x-Achsen-Anweisung schreiben. Das ist aber bei der Datenverarbeitung keine schöne Idee, das steht ja schon im Datenabschnitt.
Sieht so aus, als hätte ich keine Ahnung vom Datenumfang, vom Zugriff, von den hier verwendeten Datenstrukturen oder davon, wie ich allein anhand des PGF-Handbuchs den richtigen PGF-Schlüssel errate datavisualization
.
Kann dies nur durch die Einführung einer globalen Variable gelöst werden, z. B. als pgfkeys, l3, „Array“, Datenobjekt usw.? Und wenn ja, wird das deklarierte Format die extrahierten ursprünglichen X-Daten dort ablegen?
\documentclass[10pt,border=3mm,tikz]{standalone}
\usetikzlibrary{datavisualization}
\newcounter{NX}
% ~~~ introducing ordinal values for x ~~~~~~~~~
% converts (date,birds) into (NX,birds) in (x,y) world
\pgfdeclaredataformat{ordinalX}
{}
{}
{#1,#2}
{ % ~~~ new x-values: one-by-one ~~~~~~~~~
\pgfmathaddtocounter{NX}{1}
\pgfkeyssetvalue{/data point/x}{\theNX}
% ~~~ preserving the y-data ~~~~~~~~~~~~
\pgfkeyssetvalue{/data point/y}{#2}
% ~~~ original x-data, to be treated as labels ~~~~
\pgfkeyssetvalue{/data point/mylabel}{#1}
% ~~~ storing NX, y and (?) mylabel ~~~~~
\pgfdatapoint
}
{}{}
% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\begin{document}
\begin{tikzpicture}
\datavisualization [
scientific axes=clean,
x axis={label=X,
ticks={label=mylabel} % can't put date as labels
}, % rather it likes a list ?from data section?
y axis={label=birds},
all axes=grid,
][
visualize as line,
] data [format=ordinalX] {
% date,birds % skipping header
30/10/2023,1200
02/10/2023,1229
06/11/2023,980
09/11/2023,570
13/11/2023,308
16/11/2023,2590
20/11/2023,11700
}
% TEST / Bypass ?
% ~~~ if I had access to, say, /data point/mylabel here ...
% I might be able to iterate and place date as labels
info{
\foreach \x in {1,2,...,7}
\node[rotate=90,anchor=east,teal]
at (visualization cs: x={\x},y={-2e3}) {X-label};
}
;
\end{tikzpicture}
\end{document}
Antwort1
Ich habe eine Lösung gefunden, indem ichJakes Lösung von 2013Wichtige Punkte:
- die meisten Dinge passieren in der Aussage
x axis={..., ticks={...
- es ruft eine
typesetter
- es
styles the nodes
für die Beschriftungen (drehen usw.) - der Schriftsetzer stützt sich auf ein
global TeX list
, das wie ein Array funktioniert - im angegebenen Format in die Liste
ordinalX
aufnehmenappends
- Ich verwende ein
LaTeX counter
anstelle vonpredefined TeX \@tempcnta
,siehe hier auf StackExchange \makeatletter
und\makeatother
sind enthalten, scheinen aber keinen Effekt zu haben, wahrscheinlich aufgrund des unterschiedlichen verwendeten Zählers
\documentclass[10pt,border=3mm,tikz]{standalone}
\usetikzlibrary{datavisualization}
\newcounter{NX} % <<< using LaTeX counter istead of \@tempcnta
\makeatletter
% ~~~ introducing ordinal values for x ~~~~~~~~~
% converts (date,birds) into (NX,birds) in (x,y) world
\pgfdeclaredataformat{ordinalX}%
{} % No catcode changes
{\xdef\label@list{}}% initialise a global label list
{#1,#2}% data format
{%
\pgfmathaddtocounter{NX}{1}% advance
\pgfkeyssetvalue{/data point/x}{\theNX}%store counters result as x-data
\pgfkeyssetvalue{/data point/y}{#2}% the y-data (birds)
\xdef\label@list{\label@list,"#1"}% append label to list
\pgfdatapoint
}%
{}{}
% ~~~ typesetting the x-axis: putting labels instead of 1,2,3, ... ~~~~~~~~
\def\ticksfromlabellist#1{%
\pgfmathparse{{\label@list}[#1]}% retrieve label one by one
\pgfmathresult% result: text, i.e. 30/10/2023
}
\makeatother
% ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\begin{document}
\begin{tikzpicture}
\datavisualization [
scientific axes=clean,
x axis={
label=Date,
ticks={ % NEW
step=1,
tick typesetter/.code=\ticksfromlabellist{##1}, % typesetting labels, replacing 1,2,3,...
% style={text height=1ex}, % for proper vertical alignment
node style={rotate=90,anchor=east,teal}, % rotating etc.
}
},
y axis={label=birds},
all axes=grid,
][
visualize as line,
] data [format=ordinalX] {
% date,birds % skipping header
30/10/2023,1200
02/10/2023,1229
06/11/2023,980
09/11/2023,570
13/11/2023,308
16/11/2023,2590
20/11/2023,11700
};
\end{tikzpicture}
\end{document}