Conditional plotting based on data

Conditional plotting based on data

In the MWE below, is there a way to make the markers * inside the circle (i.e., \x^2 + \y^2 <= 1) instead of x?

\documentclass{article}
\usepackage{pgfplots}

\pgfplotsset{compat=newest}

\begin{document}
\begin{tikzpicture}

  \begin{axis}
    [anchor=origin, axis equal image, xmin=-1,xmax=1, xlabel={$x$},
    ylabel={$y$}, ymin=-1,ymax=1, ]

    \draw[thick] (-1,-1) -- (1,-1) -- (1,1) -- (-1,1) -- (-1,-1);
    \draw[thick] (0,0) circle (1);

    \addplot [only marks, mark=x, samples=500]
    ({rand}, {rand} );
\end{axis}
\end{tikzpicture}%
\end{document}

enter image description here

답변1

Complete revision: I is super simple with point meta. One only needs to define two classes and set point meta appropriately, see code.

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}
\begin{tikzpicture}

  \begin{axis}
    [anchor=origin, axis equal image, xmin=-1,xmax=1, xlabel={$x$},
    ylabel={$y$}, ymin=-1,ymax=1, ]

    \draw[thick] (-1,-1) -- (1,-1) -- (1,1) -- (-1,1) -- (-1,-1);
    \draw[thick] (0,0) circle (1);
    \clip (-1,-1) rectangle (1,1); % to prevent the marks from overshooting
    \addplot[scatter,clip=true, clip marker paths=true,
        only marks, mark=*, samples=500,
             scatter/classes={0={mark=*,blue},
                   1={mark=x,red}},point meta=int(sqrt(x^2+y^2)),
    ]({rand},{rand});
\end{axis}
\end{tikzpicture}%
\end{document}

enter image description here

The following are just more complicated artifacts.

I'd make two plots and clip them.

\documentclass{article}
\usepackage{pgfplots}


\pgfplotsset{compat=newest}

\begin{document}
\begin{tikzpicture}

  \begin{axis}
    [anchor=origin, axis equal image, xmin=-1,xmax=1, xlabel={$x$},
    ylabel={$y$}, ymin=-1,ymax=1, ]

    \draw[thick] (-1,-1) -- (1,-1) -- (1,1) -- (-1,1) -- (-1,-1);
    \draw[thick] (0,0) circle (1);
    \begin{scope}
    \clip (0,0) circle (1) (-1,-1) rectangle (1,1);
    \addplot+[clip=true, clip marker paths=true,only marks, mark=*, samples=500]({rand},{rand});
    \end{scope}
    \clip (0,0) circle (1);
    \addplot+[clip=true, clip marker paths=true,only marks, mark=x, samples=500]
    ({rand},{rand});
\end{axis}
\end{tikzpicture}%
\end{document}

enter image description here

UPDATE: Or you use the functionality of scatter plots. I just switch off the mark inside/outside the circle.

\documentclass{article}
\usepackage{pgfplots}


\pgfplotsset{compat=newest}

\begin{document}
\edef\Star{*}
\edef\X{x}
\begin{tikzpicture}
\tikzset{scatter/@pre marker code/.append style={/tikz/mark
size=\perpointmarksize}}
  \begin{axis}
    [anchor=origin, axis equal image, xmin=-1,xmax=1, xlabel={$x$},
    ylabel={$y$}, ymin=-1,ymax=1, ]

    \draw[thick] (-1,-1) -- (1,-1) -- (1,1) -- (-1,1) -- (-1,-1);
    \draw[thick] (0,0) circle (1);
    \addplot[scatter,
      scatter/use mapped color={
draw=black,
        fill=blue}, only marks, mark=*, samples=500,
             visualization depends on={int(sqrt(x^2+y^2)) \as \rad},
        scatter/@pre marker code/.append style=
            {/tikz/mark size=2*\rad}]({rand},{rand});
    \addplot[scatter,
      scatter/use mapped color={
draw=red,
        fill=red}, only marks, mark=x, samples=500,
             visualization depends on={int(2-sqrt(x^2+y^2)) \as \rad},
        scatter/@pre marker code/.append style=
            {/tikz/mark size=2*\rad}]({rand},{rand});
\end{axis}
\end{tikzpicture}%
\end{document}

enter image description here

This way the symbols do not get cut off. You can still clip against the bounding box, for instance by using the first example.

답변2

Here I present a solution that first creates the random data in a table which then is used to plot them. Separating the created points in inside and outside the circle can then easily be done by filtering.

The main difference to marmot's answer is that my solution really only prints the specified number of points while in marmots answer two times the specified number of points are created and then "filtered" for inside and outside the circle. But because random data are used it is very unlikely that exactly the number of specified points is shown in the resulting plot. So the question is, if you need exactly the specified number of points or not ...

For details please have a look at the comments in the code.

% used PGFPlots v1.15
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
    \pgfplotsset{
        % use this `compat' level or higher so circles use axis coordinates
        % as "units" when a radius is given without a unit
        compat=1.11,
    }
    % create a table containing the random data
    \pgfplotstablenew[
        % create a column for the x data
        create on use/x/.style={
            create col/expr={rand}
        },
        % create a column for the y data
        create on use/y/.style={
            create col/expr={rand}
        },
        % create a column for the vector length
        create on use/veclen/.style={
            create col/expr={sqrt( (\thisrow{x})^2 + (\thisrow{y})^2 )}
        },
        % "load" the columns which shall be used
        columns={
            x,
            y,
            veclen%
        },
    % replace the "500" to the number of sample points you want to have
    ]{500}{\datatable}
\begin{document}
\begin{tikzpicture}
    \begin{axis}[
        axis equal image,
        xmin=-1,
        xmax=1,
        ymin=-1,
        ymax=1,
        xlabel={$x$},
        ylabel={$y$},
        % moved common options here
        only marks,
    ]

        % state the radius of the circle here
        \pgfmathsetmacro{\CircleRadius}{1}

    \draw [thick] (0,0) circle (\CircleRadius);

    % add values inside the circle
    \addplot table [
        x=x,
        y expr={
            ifthenelse(
                \thisrow{veclen} <= \CircleRadius,
                \thisrow{y},
                NaN
            )
        }
    ] {\datatable};

    % add values outside the circle
    \addplot table [
        x=x,
        y expr={
            ifthenelse(
                \thisrow{veclen} > \CircleRadius,
                \thisrow{y},
                NaN
            )
        }
    ] {\datatable};
\end{axis}
\end{tikzpicture}
\end{document}

image showing the result of above code

관련 정보