Wie kann man beispielsweise die X-Achse mithilfe der Tikzlibrary-Datenvisualisierung in eine Ordinalachse mit X-Daten als Textbeschriftungen umwandeln?

Wie kann man beispielsweise die X-Achse mithilfe der Tikzlibrary-Datenvisualisierung in eine Ordinalachse mit X-Daten als Textbeschriftungen umwandeln?

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
...

\datavisualizationbietet zwei Visualisierungen, scientific axesund 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}

Ergebnis

Antwort1

Ich habe eine Lösung gefunden, indem ichJakes Lösung von 2013Wichtige Punkte:

  • die meisten Dinge passieren in der Aussagex axis={..., ticks={...
  • es ruft einetypesetter
  • es styles the nodesfü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 ordinalXaufnehmenappends
  • Ich verwende ein LaTeX counteranstelle von predefined TeX \@tempcnta,siehe hier auf StackExchange
  • \makeatletterund \makeatothersind 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}

Ergebnis

verwandte Informationen