3

I would like to create lists of ticks on the x and y axises. I noticed a method of generating a new list from this post [How to use a macro inside tick definition in pgfplots].

I modified that code into the following MWE. In my code, I wanted to create two lists of ticks based on the list {0.75,3.5,1.0,1.5,1.0,3.5,1.0,1.5}. The first list is simply to add up these values in sequence. The second list is to double the values of the first list. Then, the newly generated lists are used as the ticks of the axises.

\documentclass{article}
\usepackage{tikz}

%% Example code copied from another post.
\newcommand{\deflisttickold}[1]{
\gdef\listticksold{}% global list
\foreach \x[count=\xi] in {#1}{\global\let\maxitems\xi}% count the max number of items
\show \maxitems
\foreach \x[count=\xi] in {#1}{
    \ifnum\xi=\maxitems
        \xdef\listticksold{\listticks \x}
    \else
        \xdef\listticksold{\listticks \x,}
    \fi
    }
}

%% New code modified from \deflisttickold
\newcommand{\deflistticknewone}[1]{
\gdef\listticksnewone{}% global list
\pgfmathsetmacro{\currval}{0.0}
\foreach \x[count=\xi] in {#1}{\global\let\maxitems\xi}% count the max number of items
\foreach \x[count=\xi] in {#1}{
    \pgfmathparse{\currval+\x}
    \global\edef\currval{\pgfmathresult}
    \ifnum\xi=\maxitems
        \xdef\listticksnewone{\listticksnewone \currval}
    \else
        \xdef\listticksnewone{\listticksnewone \currval,}
    \fi
    }
}

\newcommand{\deflistticknewtwo}[1]{
\gdef\listticksnewtwo{}% global list
\pgfmathsetmacro{\lastval}{0.0}
\foreach \x[count=\xi] in {#1}{\global\let\maxitems\xi}% count the max number of items
\foreach \x[count=\xi] in {#1}{
    \pgfmathparse{2.0*(\x-\lastval)}
    \global\edef\lastval{\x}
    \ifnum\xi=\maxitems
        \xdef\listticksnewtwo{\listticksnewtwo \pgfmathresult}
    \else
        \xdef\listticksnewtwo{\listticksnewtwo \pgfmathresult,}
    \fi
    }
}

\edef\mylist{0.75,3.5,1.0,1.5,1.0,3.5,1.0,1.5}
\deflisttickold{\mylist}
\deflistticknewone{\mylist}
\deflistticknewtwo{\listticksnewone}

\begin{tikzpicture}
    \begin{axis}[
        xmode=linear,
        ymode=linear,
        axis x line*=bottom,
        axis y line*=left,
        tick label style={font=\small},
        grid=both,
        tick align=outside, 
        tickpos=left,
        width=0.65\textwidth,
        height=0.4\textwidth,
        xmin=0,
        xtick = \listticksnewone,
        xticklabels = \listticksnewone,
        ytick = \listticksnewtwo,
        yticklabels = \listticksnewtwo,
    ]

    \addplot coordinates {
        (0.25, 2.5)
        (1.5, 3)
        (3.5, 3.5)
        (5, 4.5)
        (7, 5)
    };

    \end{axis}
\end{tikzpicture}

\end{document}

However, my code does not work well. If I use the given code for replicating a list, the newly generated list by \deflisttickold{\mylist} is truly a list. The lists generated by \deflistticknewone{\mylist} and \deflistticknewtwo{\listticksnewone} are incorrect.

Can anyone help me to figure out the problems? Thanks in advance.

2 Answers2

0

One way to this is to adapt the solution from Using Macro Defined Lists in TikZ/PGFplots and define a x tick labels list style:

\edef\temp{\noexpand\pgfplotsset{x tick labels list/.style={xticklabels={\MyDoubleList}}}}
\temp

where \MyDoubleList is the new list, which is then applied as an option to the axis environment.

To create a new list based on an old list you:

  1. Define a macro which returns the new value computed from a given value. For example:

    \newcommand*{\MultiplyByTwo}[1]{2*#1}%
    

    would double the value provided.

  2. Invoke the \DefineNewList macro and pass in the

        % #1 = macro to contain new list
        % #2 = function which evaluates new list member based on old list member
        % #3 = old list
    

    So, if \mylist contains your original list, invoking

    \DefineNewList{\MyDoubleList}{\MultiplyByTwo}{\mylist}
    

    creates a list \MyDoubleList in which each element is double the value in \mylist.

Putting ths together yields labels on the x-axis at 0.5, 2.0, 4.0 which are double the actual values:

enter image description here

Code:

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.13}


\makeatletter
\newcommand*{\@tempDefineNewList}{}% Ensure it is not already defined
\newcommand*{\DefineNewList}[3]{%
    % #1 = macro to contain new list
    % #2 = function which evaluates new list member based on old list member
    % #3 = old list
    \gdef#1{}% Initialize
    \edef\expandedOldList{#3}%
    \foreach [count=\xi] \x in \expandedOldList {%
        \pgfmathsetmacro{\@tempDefineNewList}{#2{\x}}%
        \ifnum\xi=1\relax
            \xdef#1{\@tempDefineNewList}%
        \else
            \xdef#1{#1, \@tempDefineNewList}%
        \fi
    }%
}%
\makeatother

\newcommand*{\MultiplyByTwo}[1]{2*#1}%
\newcommand*{\MultiplyByThree}[1]{2*#1}%
\newcommand\mylist{0.5, 2.0, 4.0}

\DefineNewList{\MyDoubleList}{\MultiplyByTwo}{\mylist}
\DefineNewList{\MyTripleList}{\MultiplyByThree}{\mylist}

%% https://tex.stackexchange.com/questions/17833/using-macro-defined-lists-in-tikz-pgfplots
\edef\temp{\noexpand\pgfplotsset{x tick labels list/.style={xticklabels={\MyDoubleList}}}}%
\temp

\begin{document}
\begin{tikzpicture}
    \begin{axis}[
        xmode=linear,
        ymode=linear,
        axis x line*=bottom,
        axis y line*=left,
        tick label style={font=\small},
        grid=both,
        tick align=outside, 
        tickpos=left,
        width=0.65\textwidth,
        height=0.4\textwidth,
        xmin=0,
        xtick=\mylist,
        x tick labels list,% <-- see effect of commenting this out.
    ]

    \addplot coordinates {
        (0.25, 2.5)
        (1.5, 3)
        (3.5, 3.5)
        (5, 4.5)
        (7, 5)
    };

    \end{axis}
\end{tikzpicture}
Peter Grill
  • 223,288
  • Thanks for the answer. My question is still not fully answered. I would like to know the code for a more complicated computation on list. For example, I want to get the list of partial sum of a given list. Given a list {v_1, v_2, ..., v_k}. The list I want to compute is {v_1, v_1+v_2, v_1+v_2+v_3, ..., v_1+...+v_k}. What is the code for doing this computation? Thanks. – Novice User Sep 01 '16 at 13:51
  • 1
    @NoviceUser: As that is quite different than the thrust of this question about how to use a macro defined list in pgfplots, I suggest you post a new question asking how to define a macro that returns such a list. – Peter Grill Sep 02 '16 at 07:31
0

I have found an answer to my question.

Code segment is as follows.

\newcommand{\deflisttick}[1]{
\gdef\listticks{}% global list
\pgfmathsetmacro{\currval}{0.0}
\foreach \x [count=\xi] in #1 {\global\edef\maxitems{\xi}}% count the max number of items
\foreach \x [count=\xi] in #1 {
    \pgfmathparse{\currval+\x}
    \global\edef\currval{\pgfmathresult}
    \ifnum\xi=\maxitems
        \global\edef\listticks{\listticks \currval}
    \else
        \global\edef\listticks{\listticks \currval,}
    \fi
    }
}

\edef\mylist{0.75,3.5,1.0,1.5,1.0,3.5,1.0,1.5}
\deflisttick{\mylist}

\begin{tikzpicture}
    \begin{axis}[
        xmode=linear,
        ymode=linear,
        axis x line*=bottom,
        axis y line*=left,
        tick label style={font=\small},
        grid=both,
        tick align=outside, 
        tickpos=left,
        width=0.65\textwidth,
        height=0.4\textwidth,
        xmin=0, xmax=15,
        xtick = \listticks,
    ]

    \addplot coordinates {
        (0.25, 2.5)
        (1.5, 3)
        (3.5, 3.5)
        (5, 4.5)
        (7, 5)
    };

    \end{axis}
\end{tikzpicture}

A new list is created as the partial sum of a given list. The list of partial sum is used as the list of xticks. This code segment will produce a figure as shown.enter image description here