获取 xmax 处线性回归图的 y 值

获取 xmax 处线性回归图的 y 值

我正在创建一个动态 LaTeX (LuaLaTeX) 脚本,该脚本会根据给定的 CSV 文件创建图表。xmin、xmax 等设置取决于该 CSV 文件。

该 CSV 文件包含硬盘的存储使用情况以及日期时间戳。

该图的范围从两年前到未来一年。黑色图显示 CSV 数据,粗红色线为线性回归线,在两个方向上扩展(使用“缩短”键)。线性回归是使用此代码创建的:

\addplot [line width=10pt, opacity=.3, red, shorten >= -10cm, shorten <= -10cm]  table [
            x index=5,
            y={create col/linear regression={
                x=JulianDayMod,
                y="size",
            }}
        ] {\loadedtable};

由于 CSV 具有日期格式,我需要预先使用此脚本对其进行转换:pgfplots 中 x 轴上有日期的线性回归

现在我需要 xmax 处的线性回归的 y 值。你知道如何获取它吗?
(同样重要的是要知道 xmax 也是一个日期,例如“2022-11-23”)

它应该显示在我放置占位符的图例中。我已经知道您可以使用和x访问线性回归的系数。我可以使用访问 xmax\pgfplotstableregressiona\pgfplotstableregressionb
\pgfkeysgetvalue{/pgfplots/xmax}{\xmax}

但我在网上找不到任何解决方案......

在此处输入图片描述

答案1

经过尝试,我找到了解决方案!
(我心中已经有了正确的想法,但第一次运行没有奏效......)

回顾:线性函数具有以下功能:a · x + b

并允许pgfplotstable您访问
a线性\pgfplotstableregressiona回归图。
b\pgfplotstableregressionb

所以我用这个代码来访问该值:(xmin 是先前定义的)

% get xmax (e.g. 2021-11-25)
\pgfkeysgetvalue{/pgfplots/xmax}{\xmax}

% convert xmax (date to julian, which is an integer number)
\newcount\xmaxjulian
\pgfcalendardatetojulian{\xmax}{\xmaxjulian}
\xmaxjulian=\numexpr\xmaxjulian-\xmin % remove offset

% store y value at xmax in \var
\pgfmathsetmacro{\var}{\pgfplotstableregressiona * (\the\xmaxjulian) + \pgfplotstableregressionb}


% print legend:
\addlegendentry{Forecast utilization in one year:
   \luaexec{ tex.sprint ( string.format ( "\%.2f" , \var )  ) } TB}

笔记:
该代码\luaexec{ tex.sprint ( string.format ( "\%.2f" , \var ) ) }将我的值四舍五入到小数点后两位。它仅适用于 LuaLaTeX,您需要将其添加\usepackage{luacode}到代码中。

笔记2:
您可以使用以下命令打印线性回归函数:

Formula of linear regression: 
       $\pgfmathprintnumber{\pgfplotstableregressiona}\cdot x
       \pgfmathprintnumber[print sign]{\pgfplotstableregressionb}$

注3:
我在这里添加了一个 MWE 示例:(您需要 LuaLaTeX 才能运行它)

\documentclass{article}
\usepackage[letterpaper,top=2cm,bottom=2cm,left=3cm,right=3cm,marginparwidth=1.75cm]{geometry}
\usepackage{datatool}
\usepackage{luacode}

\usepackage{pgfplots}
\usepackage{pgfplotstable}
\usepackage{pgfcalendar}
\usepgfplotslibrary{dateplot}
\pgfplotsset{compat=newest}


\begin{filecontents*}{data.csv}
date, size
2021-04-01, 1.42
2021-05-01, 1.46
2021-06-01, 1.58
2021-07-01, 1.55
2021-08-01, 1.69
\end{filecontents*}


\begin{document}
\thispagestyle{empty}
\centering


\pgfplotstableread[col sep=comma]{data.csv}\loadedtable

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% add new column with Julian integer numbers
    \newcount\julianday
    \pgfplotstablecreatecol[
        create col/assign/.code={
            \pgfcalendardatetojulian{\thisrowno{0}}{\julianday}
            \edef\entry{\the\julianday}
            \pgfkeyslet{/pgfplots/table/create col/next content}\entry
        },
    ]{JulianDay}{\loadedtable}
        \pgfplotstablegetelem{0}{JulianDay}\of{\loadedtable}
        \pgfmathtruncatemacro{\xmin}{\pgfplotsretval}
    \pgfplotstablecreatecol[
        expr={\thisrow{JulianDay}-\xmin},
    ]{JulianDayMod}{\loadedtable}
% source: https://tex.stackexchange.com/questions/367339/linear-regression-with-dates-on-x-axis-in-pgfplots


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% compute dates for xmin and xmax

% get last date in file
\DTLloaddb[%
    noheader,%
    keys={date,2}%
    ]{myDB}{data.csv}
\DTLforeach*{myDB}{\CurrentA=date}{%
    \xdef\LastDate{\CurrentA}
}
\newcount\DateOfLastScan
\pgfcalendardatetojulian{\LastDate{}}{\DateOfLastScan}
\pgfcalendarjuliantodate{\DateOfLastScan}{\theyear}{\themonth}{\theday}
\year=\theyear
\month=\themonth
\day=\theday

% get date two years ago
\year=\numexpr\year-2
\edef\twoyearsago{\the\year-\ifnum\the\month<10 0\fi\the\month-\ifnum\the\day<10 0\fi\the\day}
\year=\numexpr\year+2

% get date one year in the future
\year=\numexpr\year+1
\edef\oneyearfuture{\the\year-\ifnum\the\month<10 0\fi\the\month-\ifnum\the\day<10 0\fi\the\day}
\year=\numexpr\year-1


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% print plot

\begin{tikzpicture}
\begin{axis}
[
    date coordinates in=x,
    ylabel={Terabyte}, 
    xticklabel style={rotate=90,anchor=near xticklabel},
    xticklabel=\scriptsize\texttt{\day-\month-\year},
    yticklabel={\luaexec{ tex.sprint ( string.format ( "\%.2f" , \tick )  ) }},
    grid,
    tick align=inside,
    width=\textwidth,
    xmin=\twoyearsago{},
    xmax=\oneyearfuture{},
    ymin=-0.05,
    legend pos = south east,
    legend image post style={only marks, mark=none},
    legend cell align={left},
]


% linear regression
\addplot [line width=10pt, opacity=.3, red, shorten >= -10cm, shorten <= -10cm]  table [
            x index=0,
            % now we can use the newly created column to do the linear regression
            y={create col/linear regression={
                x=JulianDayMod,
                y=size,
            }}
       ] {\loadedtable};
    
% contents from CSV file        
\addplot[thick, no marks, solid] table[col sep=comma, x index=0, y index=1]{\loadedtable};


% get y value at xmax
\pgfkeysgetvalue{/pgfplots/xmax}{\xmax}
\newcount\xmaxjulian
\pgfcalendardatetojulian{\xmax}{\xmaxjulian}
\xmaxjulian=\numexpr\xmaxjulian-\xmin
\pgfmathsetmacro{\var}{\pgfplotstableregressiona * (\the\xmaxjulian) + \pgfplotstableregressionb}

% add legends
\addlegendentry{Forecast utilization in one year: \textbf{\luaexec{% 
   tex.sprint ( string.format ( "\%.2f" , \var )  ) } TB}}
\addlegendentry{Formula of linear regression: 
    $\pgfmathprintnumber{\pgfplotstableregressiona}\cdot x
    \pgfmathprintnumber[print sign]{\pgfplotstableregressionb}$
    }
    
    
% add invisible point at end of linear regression to keep the end of line inside of the plot
\addplot[forget plot,draw=none] coordinates {(\xmax,\var)};


\end{axis}
\end{tikzpicture}
\end{document}

结果:
在此处输入图片描述

相关内容