¿Cómo convertir, digamos, el eje x, en un eje ordinal con datos x como etiquetas textuales usando la visualización de datos de tikzlibrary?

¿Cómo convertir, digamos, el eje x, en un eje ordinal con datos x como etiquetas textuales usando la visualización de datos de tikzlibrary?

Fondo

Supongamos que tiene datos como estos en la sección de datos de datavisualization, que también podrían provenir de un archivo,

        date,birds      
        30/10/2023,1200
        02/10/2023,1229
...

o

        species,birds       
        spec4,1200
        spec1,1229
...

\datavisualizationproporciona dos visualizaciones, scientific axesy school book axes, que requieren datos xy.

Pregunta

No es gran cosa reemplazar los datos x textuales por un contador, para introducir una escala ordinal simple. Pero, ¿cómo conservar o acceder a los datos x originales Y ponerlos como etiquetas en el eje x en lugar de 1,2,...?

Intentos

El siguiente código proporciona \pgfdeclaredataformat{ordinalX}, que reemplaza x-data por un simple contador NX.

Sé que yopodríaescriba una lista, por ejemplo, a través de ticks={major at={1 as spec4,...}}, a mano en la declaración del eje x. Pero esa no es una buena idea cuando se procesan datos, como ya se mencionó en la sección de datos.

Parece que no tengo idea sobre el alcance de los datos, el acceso, las estructuras de datos utilizadas aquí o incluso adivinar la pgfkey correcta solo del pgfmanual wrt datavisualization.

¿Esto sólo se puede resolver introduciendo una variable global, por ejemplo, como pgfkeys, l3, "array", objeto de datos, etc.? Y si es así, ¿el formato declarado colocará allí los datos x originales extraídos?

\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}

resultado

Respuesta1

Encontré una solución usando y adaptandoLa solución de Jake de 2013.. Puntos clave:

  • la mayoría de las cosas suceden en la declaraciónx axis={..., ticks={...
  • llama untypesetter
  • styles the nodespara las etiquetas (rotar, etc. )
  • el tipógrafo se basa en a global TeX list, que funciona como una matriz
  • dentro del formato declarado ordinalXa appendsdicha lista
  • Yo uso a LaTeX counteren lugar de predefined TeX \@tempcnta,ver aquí en StackExchange
  • \makeatlettery \makeatotherestán incluidos, pero no parecen tener efecto, probablemente debido al diferente contador utilizado
\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}

resultado

información relacionada