当数据中有 NaN 行时,箱线图为空

当数据中有 NaN 行时,箱线图为空

我已经有一个相当复杂的设置,其中我读取文件中的箱线图数据、这些文件的名称列表以及用于绘制每个文件的箱线图的循环。然而,这个文件的其中一行没有数据,用一行全是 NaN 来表示。我需要一种不产生错误的方式来应对这种情况(我使用 externalize 来生成这些图,任何错误的图都会产生致命错误)。

这是一个不那么简单的例子:

% !TEX program = lualatex
% !TeX encoding = UTF-8

\documentclass{article}  
\usepackage{pgfplots}
\pgfplotsset{compat=1.13}
\usepgfplotslibrary{statistics}
\usetikzlibrary{pgfplots.groupplots}
\usepackage{pgffor}
\usepackage{filecontents}

\begin{filecontents}{dataA.txt}
row min   Q1   median Q3    max
A   8e-4  2e-1 3e-2   4e-3  6e0
B   2e-4  1e-1 2e-1   3e-1  9e-1
C   1e-3  5e-1 3e0    4e0   5e0
D   1e-2  1e0  2e0    3e0   4e0 
E   2e-10  8e-2 3e-1   4e-1  1e0
F   8e-12 3e-1 6e-1   1e0   2e0 
\end{filecontents}

\begin{filecontents}{dataB.txt}
row min   Q1   median Q3    max
A   NaN   NaN  NaN    NaN   NaN
B   2e-4  1e-1 2e-1   3e-1  9e-1
C   1e-3  5e-1 3e0    4e0   5e0
D   1e-2  1e0  2e0    3e0   4e0 
E   2e-10  8e-2 3e-1   4e-1  1e0
F   8e-12 3e-1 6e-1   1e0   2e0 
\end{filecontents}

\makeatletter
\pgfplotsset{
    boxplot prepared from table/.code={
        \def\tikz@plot@handler{\pgfplotsplothandlerboxplotprepared}%
        \pgfplotsset{
            /pgfplots/boxplot prepared from table/.cd,
            #1,
        }
    },
    /pgfplots/boxplot prepared from table/.cd,
        table/.code={\pgfplotstablecopy{#1}\to\boxplot@datatable},
        row/.initial=0,
        make style readable from table/.style={
            #1/.code={
                \pgfplotstablegetelem{\pgfkeysvalueof{/pgfplots/boxplot prepared from table/row}}{##1}\of\boxplot@datatable
                \pgfplotsset{boxplot/#1/.expand once={\pgfplotsretval}}
            }
        },
        make style readable from table=lower whisker,
        make style readable from table=upper whisker,
        make style readable from table=lower quartile,
        make style readable from table=upper quartile,
        make style readable from table=median,
        make style readable from table=lower notch,
        make style readable from table=upper notch
}
\makeatother

\newcommand{\BoxPlot}[1]{ % \BoxPlot{\file}
\begin{tikzpicture}
    \begin{semilogyaxis}[
    boxplot/draw direction=y,
    width=0.7\textwidth,
    xmin=0,xmax=7,
    xtick={1,2,3,4,5,6},
    xticklabels={A,B,C,D,E,F}]

    \pgfplotsforeachungrouped \i in {0,1,2,3,4,5} {
        \edef\temp{
            \noexpand\addplot+ [
            boxplot prepared from table={
                table=\noexpand#1,
                row=\i,
                lower whisker=min,
                upper whisker=max,
                lower quartile=Q1,
                upper quartile=Q3,
                median=median
            }, boxplot prepared
            ]
            coordinates {};
        }
        \temp
    }
    \end{semilogyaxis}
\end{tikzpicture}
}

\begin{document}

\newcommand*{\ListOfFiles}{%
dataA,
dataB%
}

\foreach \x in \ListOfFiles {
    \pgfplotstableread{\x.txt}{\DATA}
    \begin{figure}[htpb]
        \centering
        \BoxPlot{\DATA}
        \caption{Here is \x}
    \end{figure}
}

\end{document}

理想情况下,遇到 NaN 行时根本不会绘制任何图。但生成没有任何错误的图才是最重要的。

在此处输入图片描述

答案1

我找到了一个解决方法(但仍然欢迎更清洁的解决方案):

设置值的限度ymax(例如1e2),并将更高的数字作为箱线图的数据(例如2e2)。这样,箱线图就简单地绘制在显示范围之外:

% !TEX program = lualatex
% !TeX encoding = UTF-8

\documentclass{article}  
\usepackage{pgfplots}
\pgfplotsset{compat=1.13}
\usepgfplotslibrary{statistics}
\usetikzlibrary{pgfplots.groupplots}
\usepackage{pgffor}
\usepackage{filecontents}

\begin{filecontents}{dataA.txt}
row min   Q1   median Q3    max
A   8e-4  2e-1 3e-2   4e-3  6e0
B   2e-4  1e-1 2e-1   3e-1  9e-1
C   1e-3  5e-1 3e0    4e0   5e0
D   1e-2  1e0  2e0    3e0   4e0 
E   2e-10  8e-2 3e-1   4e-1  1e0
F   8e-12 3e-1 6e-1   1e0   2e0 
\end{filecontents}

\begin{filecontents}{dataB.txt}
row min   Q1   median Q3    max
A   200   200  200    200   200
B   2e-4  1e-1 2e-1   3e-1  9e-1
C   1e-3  5e-1 3e0    4e0   5e0
D   1e-2  1e0  2e0    3e0   4e0 
E   2e-10  8e-2 3e-1   4e-1  1e0
F   8e-12 3e-1 6e-1   1e0   2e0 
\end{filecontents}

\makeatletter
\pgfplotsset{
    boxplot prepared from table/.code={
        \def\tikz@plot@handler{\pgfplotsplothandlerboxplotprepared}%
        \pgfplotsset{
            /pgfplots/boxplot prepared from table/.cd,
            #1,
        }
    },
    /pgfplots/boxplot prepared from table/.cd,
        table/.code={\pgfplotstablecopy{#1}\to\boxplot@datatable},
        row/.initial=0,
        make style readable from table/.style={
            #1/.code={
                \pgfplotstablegetelem{\pgfkeysvalueof{/pgfplots/boxplot prepared from table/row}}{##1}\of\boxplot@datatable
                \pgfplotsset{boxplot/#1/.expand once={\pgfplotsretval}}
            }
        },
        make style readable from table=lower whisker,
        make style readable from table=upper whisker,
        make style readable from table=lower quartile,
        make style readable from table=upper quartile,
        make style readable from table=median,
        make style readable from table=lower notch,
        make style readable from table=upper notch
}
\makeatother

\newcommand{\BoxPlot}[1]{ % \BoxPlot{\file}
\begin{tikzpicture}
    \begin{semilogyaxis}[
    boxplot/draw direction=y,
    width=0.7\textwidth,
    xmin=0,xmax=7,
    ymin=1e-11,ymax=1e2,
    xtick={1,2,3,4,5,6},
    xticklabels={A,B,C,D,E,F}]

    \pgfplotsforeachungrouped \i in {0,1,2,3,4,5} {
        \edef\temp{
            \noexpand\addplot+ [
            boxplot prepared from table={
                table=\noexpand#1,
                row=\i,
                lower whisker=min,
                upper whisker=max,
                lower quartile=Q1,
                upper quartile=Q3,
                median=median
            }, boxplot prepared
            ]
            coordinates {};
        }
        \temp
    }
    \end{semilogyaxis}
\end{tikzpicture}
}

\begin{document}

\newcommand*{\ListOfFiles}{%
dataA,
dataB%
}

\foreach \x in \ListOfFiles {
    \pgfplotstableread{\x.txt}{\DATA}
    \begin{figure}[htpb]
        \centering
        \BoxPlot{\DATA}
        \caption{Here is \x}
    \end{figure}
}

\end{document}

在此处输入图片描述

相关内容