自动将相同的值合并到 \multirow

自动将相同的值合并到 \multirow

我正在从数据文件生成 pgfplotstable。在该文件中,在列中Class,具有相同值的后续行应自动合并/折叠/连接以形成\multirow{n}{*}{value}n其中是列中具有相同值的后续行的数量Class

首次遇到某个值时无法预测该数字n。如何实现自动化?
如果稍后再次遇到某个值(例如 Mammal),则该行应该不是向上移动到任何以前遇到的版本。

梅威瑟:
渲染

\documentclass{standalone}

\usepackage{filecontents}
\usepackage{pgfplotstable}
\usepackage{booktabs}
\usepackage{multirow}
\usepackage{color}

\begin{filecontents}{data.csv}
Class,Genus
Mammal,Dog
Mammal,Cat
Mammal,Mouse
Bird,Chicken
Bird,Duck
Insect,Fly
Mammal,Bear
\end{filecontents}

\begin{document}
\pgfplotstabletypeset[
    col sep=comma,
    string type,
    every head row/.style={before row={
        \multicolumn{2}{c}{\textcolor{red}{Not what I want:}}\\\toprule},
        after row=\midrule},
    every last row/.style={after row=\bottomrule},
]{data.csv}

\pgfplotstabletypeset[
    col sep=comma,
    string type,
    every head row/.style={before row={
        \multicolumn{2}{c}{\textcolor{green}{What I want to automate:}}\\\toprule},
        after row=\midrule},
    every last row/.style={after row=\bottomrule},
]{
Class,Genus
\multirow{3}{*}{Mammal},Dog
%multirow should be extended automatically with each new Mammal row that's printed
,Cat
,Mouse
\multirow{2}{*}{Bird},Chicken
%multirow should be extended automatically with each new Bird row that's printed
,Duck
Insect,Fly
Mammal,Bear
}
\end{document}

答案1

这种方法不使用tabularmultirow,而是逐行检查输入文件并保存与给定类相关的属字符串。完成后,它使用堆栈构建与相关类相邻的属。

这将输入文件作为空格分隔的数据(请参阅本答案的附录以获取与 csv 兼容的代码)。如果您的条目是单个单词,则这种空格分隔方法可以正常工作。如果条目不止一个单词,您可以~在条目内使用它作为硬空格分隔符,或者您可以转到本答案末尾的附录。

因为这种方法不使用tabular环境,所以如果将答案放在table浮动环境之外,则当数据列表太长时将允许分页。

修改后的解决方案(符合OP的分组规范):

这个解决方案实际上比我原来的方法更简单,原来的方法经过了额外的排序步骤。

\documentclass{article}
\usepackage{filecontents,readarray,stackengine}
\begin{filecontents*}{data.ssv}
Class Genus
Mammal Dog
Mammal Cat
Mammal Mouse
Bird Chicken
Bird Duck
Insect Fly
Mammal Bear
\end{filecontents*}
\newcounter{entryindex}
\newcounter{classes}
\setstackEOL{\&}
\setstackgap{L}{12pt}

\def\doubleexpandedCS{\expandafter\expandafter\expandafter%
  \Centerstack\expandafter\expandafter\expandafter}

\def\processfile#1{%
  \readdef{#1}{\tmpa}%
  \readArrayij{\tmpa}{mydata}{2}%
  \setcounter{entryindex}{0}%
  \whiledo{\value{entryindex} < \mydataROWS}{%
    \stepcounter{entryindex}%
    \edef\theClass{\arrayij{mydata}{\arabic{entryindex}}{1}}%
    \edef\theGenus{\arrayij{mydata}{\arabic{entryindex}}{2}}%
    \def\classexists{F}%
    \ifnum\value{classes}>0
      \ifthenelse{\equal{%
        \csname Class\romannumeral\value{classes}\endcsname}{\theClass}}%
        {\def\classexists{T}}{}%
    \fi%
    \if F\classexists%
      \stepcounter{classes}%
      \expandafter\edef\csname Class%
        \romannumeral\value{classes}\endcsname{\theClass}%
      \expandafter\edef\csname theGenuses%
        \romannumeral\value{classes}\endcsname{\theGenus}%
    \else
      \expandafter\edef\csname theGenuses%
        \romannumeral\value{classes}\endcsname{%
         \csname theGenuses\romannumeral\value{classes}\endcsname%
         \&\theGenus}%
    \fi%
  }%
}

\def\showresults{%
  \noindent\hbox to 2in{\hrulefill}\par\noindent
  \makebox[1in]{\Classi}\makebox[1in]%
    {\doubleexpandedCS{\csname theGenusesi\endcsname}}\\
  \raisebox{.5\baselineskip}{\hbox to 2in{\hrulefill}}\par\noindent
  \setcounter{entryindex}{1}%
  \whiledo{\value{entryindex}<\value{classes}}{%
    \stepcounter{entryindex}%
    \makebox[1in]{\csname Class\romannumeral\value{entryindex}\endcsname}%
    \makebox[1in]{\doubleexpandedCS{\csname theGenuses%
      \romannumeral\value{entryindex}\endcsname}}\smallskip\\
  }%
}
\begin{document}

\processfile{data.ssv}

Not counting the header, there are \the\numexpr\theclasses-1\relax\ class
entries:

\begin{table}[ht]
{\centering\showresults\par}
\end{table}
And here is the following text

\end{document}

在此处输入图片描述

如果希望“类”与“属”列表顶部对齐,则重新定义

\def\doubleexpandedCS{\strutlongstacks{T}\expandafter\expandafter\expandafter%
  \Longunderstack\expandafter\expandafter\expandafter}

会产生

在此处输入图片描述

如果不喜欢相邻类之间的小跳跃,则消除定义\smallskip末尾的结果\showresults

在此处输入图片描述


附录:

如果需要以逗号分隔而不是以空格分隔的数据,则使用新的readarray包功能,可以\readarraysepchar{,}在调用之前设置解析分隔符\processfile

答案2

为了补充解决方案multirow中的答案pgfplotstable,我们可以检查下一行条目并将该重复项保存在计数器中。当下一行不同(与相比\ifx)时,我们就会分支到多行条目。这是可能的,因为多行巧妙地允许覆盖的总行数为负数。然后剩下的步骤是在表中创建另一行,以保存我们刚刚过滤的唯一条目。

一个缺点是,我们无法直接从文件中读取,而是需要先将其读入宏,然后创建唯一列(保存在名称下u-<colname>),然后使用原始列名声明对其进行排版。以下是完整的示例

\documentclass[border=5mm]{standalone}
\usepackage{filecontents}
\usepackage{pgfplotstable}
\usepackage{booktabs}
\usepackage{multirow}
\pgfplotsset{compat=1.12}


\begin{filecontents*}{data.csv}
Class,Genus
Mammal,Dog
Mammal,Cat
Mammal,Mouse
Bird,Chicken
Bird,Duck
Insect,Fly
Mammal,Bear
\end{filecontents*}

\newcount\pgfplotstableuniqueentry
\pgfplotstableuniqueentry=0
\def\pgfplotstableadduniquecol#1#2{%
    \pgfplotstablecreatecol[
        create col/assign/.code={%
            \getthisrow{#1}\entry\getnextrow{#1}\nextentry% This and next for comparison
            \ifx\entry\nextentry\relax% Compare
                \xdef\tempentry{\entry}% Save it to some macro
                \pgfkeyssetvalue{/pgfplots/table/create col/next content}{}% Empty cell
                \global\advance\pgfplotstableuniqueentry1\relax%Increment the dup count
            \else%
                \ifnum\the\pgfplotstableuniqueentry>0\relax% If there is a duplicate
                    \advance\pgfplotstableuniqueentry1% increment for multirow
                    \edef\temp{\noexpand%Selectively expand some macros
                    \pgfkeyssetvalue{/pgfplots/table/create col/next content}{%
                        \noexpand%
                        \multirow{-\the\pgfplotstableuniqueentry}{*}{\tempentry}
                    }}\temp% Execute the expanded version
                    \global\pgfplotstableuniqueentry=0%Reset dup counter
                \else%
                    \pgfkeyslet{/pgfplots/table/create col/next content}{\entry}%Do nothing
                \fi%
            \fi%
        }
    ]{u-#1}{#2}%
}



\begin{document}
\pgfplotstableread[col sep=comma]{data.csv}\mytable %Read the table
\pgfplotstableadduniquecol{Class}{\mytable} % Add the unique column

\pgfplotstabletypeset[string type,
    every head row/.style={before row=\toprule},
    every last row/.style={after row=\bottomrule},
    columns={u-Class,Genus},
    columns/u-Class/.style={column name=Class}
]{\mytable}

\end{document}

在此处输入图片描述

相关内容