如何使用 tikzlibrary 資料視覺化將 x 軸轉換為序數軸,並將 x 資料作為文字標籤?

如何使用 tikzlibrary 資料視覺化將 x 軸轉換為序數軸,並將 x 資料作為文字標籤?

背景

假設您在 的數據部分中有這樣的數據datavisualization,這些數據也可能來自文件,

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

或者

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

\datavisualization提供兩種視覺化效果scientific axesschool book axes,兩者都需要 xy 資料。

問題

用計數器取代文字 x 資料並引入簡單的序數標度並不是什麼大問題。但是如何保留或存取原始 x 資料並將它們作為標籤放在 x 軸上而不是 1,2,... ?

嘗試

下面的程式碼提供了\pgfdeclaredataformat{ordinalX},它用一個簡單的計數器 NX 取代了 x-data。

我知道我可以將清單(例如 via ticks={major at={1 as spec4,...}})手動寫入 x 軸語句中。但在處理數據時,這不是一個好主意,數據部分已經給了。

看起來我不知道這裡使用的資料範圍、存取權限、資料結構,甚至不知道僅從 pgfmanual wrt 中猜測正確的 pgfkey datavisualization

這只能透過引入全域變數(例如 pgfkeys、l3、「陣列」、資料物件等)來解決嗎?如果是這樣,聲明的格式會將提取的原始 x 資料放在那裡嗎?

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

結果

答案1

我找到了一個使用和適應的解決方案傑克 2013 年的解決方案。關鍵點:

  • 大多數事情發生在聲明中x axis={..., ticks={...
  • 它調用一個typesetter
  • 用於styles the nodes標籤(旋轉等)
  • 排字機依賴 a global TeX list,其功能類似於數組
  • 在聲明的格式內ordinalXappends到所述列表
  • 我用 aLaTeX counter代替predefined TeX \@tempcnta,請參閱 StackExchange 上的此處
  • \makeatletter\makeatother被包括在內,但似乎沒有產生效果,可能是由於使用了不同的計數器
\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}

結果

相關內容