按列进行表格输入(即转置表格)

按列进行表格输入(即转置表格)

我希望能够像以下示例一样转置tabular( x) 表。这不需要完全自动化,但我不想更改数据顺序,这很痛苦而且很愚蠢。我说的“不是完全自动化”是指,例如,标题可以单独完成等等。

让我们看看MWE:

\documentclass{article}

\usepackage{booktabs}
\def\Midrule{\midrule[\heavyrulewidth]}

\begin{document}

\centering

\begin{tabular}{*6c}\toprule
\bfseries Name & Alice & Bob & Chuck & Dave & Eve\\\Midrule
\bfseries Sex & Female & Male & Male & Male & Female\\\midrule
\bfseries Age & 18 & 19 & 20 & 21 & 22\\\bottomrule
\end{tabular}

\bigskip

Which I want to look like

\bigskip

\begin{tabular}{*3c}\toprule
\bfseries Name & \bfseries Sex & \bfseries Age\\\Midrule
Alice & Female & 18\\\midrule
Bob & Male & 19\\\midrule
Chuck & Male & 20\\\midrule
Dave & Male & 21\\\midrule
Eve & Female & 22\\\bottomrule
\end{tabular}


\end{document}

平均能量损失

注意:我知道有一个expl3解决方案,但我想在没有它的情况下得到它expl3(主要是因为人们可能会经常使用我的代码并安装旧的 LaTeX 并且我无法说服他们改变这一点)。

答案1

在此处输入图片描述

你可以\valign使用\halign

\documentclass{article}

\usepackage{booktabs,array}
\def\Midrule{\midrule[\heavyrulewidth]}
\newcount\rowc

\makeatletter
\def\ttabular{%
\hbox\bgroup
\let\\\cr
\def\rulea{\ifnum\rowc=\@ne \hrule height 1.3pt \fi}
\def\ruleb{
\ifnum\rowc=1\hrule height 1.3pt \else
\ifnum\rowc=6\hrule height \heavyrulewidth 
   \else \hrule height \lightrulewidth\fi\fi}
\valign\bgroup
\global\rowc\@ne
\rulea
\hbox to 10em{\strut \hfill##\hfill}%
\ruleb
&&%
\global\advance\rowc\@ne
\hbox to 10em{\strut\hfill##\hfill}%
\ruleb
\cr}
\def\endttabular{%
\crcr\egroup\egroup}


\begin{document}

\centering


\begin{ttabular}
\bfseries Name & Alice & Bob & Chuck & Dave & Eve\\
\bfseries Sex & Female & Male & Male & Male & Female\\
\bfseries Age & 18 & 19 & 20 & 21 & 22\\
\end{ttabular}



\bigskip

Which I want to look like

\bigskip

\begin{tabular}{*3c}\toprule
\bfseries Name & \bfseries Sex & \bfseries Age\\\Midrule
Alice & Female & 18\\\midrule
Bob & Male & 19\\\midrule
Chuck & Male & 20\\\midrule
Dave & Male & 21\\\midrule
Eve & Female & 22\\\bottomrule
\end{tabular}


\end{document}

答案2

Apgfplotstable解决方法也很方便。

\documentclass{article}
\usepackage{booktabs}
\usepackage{pgfplotstable}
\begin{document}
\pgfplotstableread{
Name   Alice   Bob   Chuck   Dave   Eve
Sex   Female   Male   Male   Male   Female
Age  18   19   20   21   22
}\mywidetable

\pgfplotstabletranspose[string type,
                        colnames from=Name,
                        input colnames to=Name
                        ]\mytalltable{\mywidetable}

\pgfplotstabletypeset[string type,
        every head row/.style={before row=\toprule,after row=\midrule},
        every last row/.style={after row=\bottomrule},
        after row=\midrule
]{\mytalltable}


\end{document}

在此处输入图片描述

如果你实在不想触碰数据,那么你可以col sep=&,row sep=\\向中添加键\pgfplotstableread

答案3

这是一个替代解决方案,使用 包裹collcell 和这个结合 包裹datatool 存储每个数据元素以供后续处理。因此,以下代码:

\begin{Ttabular}{cccccc}
    \bfseries Name & Alice & Bob & Chuck & Dave & Eve\\
    \bfseries Sex & Female & Male & Male & Male & Female\\
    \bfseries Age & 18 & 19 & 20 & 21 & 22\\
\end{Ttabular}

产量:

在此处输入图片描述

包裹environ用于以便我们可以将原始表格排版成这样\savebox它就不会在输出中产生不需要的空间。

笔记:

  • 原始列规范应用于转置表。因此,原始表中的列数必须大于行数。否则,只需在源表中过度指定表格列(因为它应用于行数)。在此示例中,前三列规范应用于转置表,其他列被忽略。

进一步增强:

  • 标题行后面的行是\midrule。我尝试了不少方法来实现\Midrule这一点,但都无法让它工作。我认为结合了\DTliflasrow 的等效项可以解决这个问题,但无法让它工作。我开始意识到这tabular比我想象的还要棘手。

代码:

\documentclass{article}
\usepackage{collcell}
\usepackage{xstring}
\usepackage{datatool}
\usepackage{booktabs}
\usepackage{environ}
%\usepackage{showframe}

\def\Midrule{\midrule[\heavyrulewidth]}

\newcounter{CurrentRow}% = column of transposed table
\newcounter{CurrentColumn}
\setcounter{CurrentColumn}{0}
\newtoggle{DoneWithFirstRow}

\newlength{\WidthAdjustment}
\newcommand*{\FirstColumn}[1]{%
    \IfEq{\arabic{CurrentColumn}}{0}{%
        % This is the start of the very first data entry in first row.
        \global\togglefalse{DoneWithFirstRow}%
        \setcounter{CurrentRow}{1}% initial value
    }{%
        % We have already completed a row. Now starting a new row.
        \global\toggletrue{DoneWithFirstRow}%
        \stepcounter{CurrentRow}%
    }%
    \setcounter{CurrentColumn}{0}%
    \NewData{#1}%
}
\newcommand*{\NewData}[1]{%
    \dtlexpandnewvalue%
    \stepcounter{CurrentColumn}%
    \iftoggle{DoneWithFirstRow}{%
        \dtlgetrow{TransposedTabularDB}{\arabic{CurrentColumn}}%
        \dtlappendentrytocurrentrow{\Alph{CurrentRow}}{#1}%
        \dtlrecombine%
    }{%
        \DTLnewrow{TransposedTabularDB}%
        \DTLnewdbentry{TransposedTabularDB}{\Alph{CurrentRow}}{#1}%
    }%
}%

\newcolumntype{F}{>{\collectcell\FirstColumn}c<{\endcollectcell}}
\newcolumntype{C}{>{\collectcell\NewData}{c}<{\endcollectcell}}

%% No longer needed since we switched to NewEnviron
%% https://tex.stackexchange.com/questions/12234/how-do-i-expand-a-macro-into-a-tabular-head
%\newcommand{\SaveColumnSpecificationAsZ}[1]{\newcolumntype{Z}{#1}}


\newtoggle{EncounteredDataRow}

\newsavebox{\TempBox}
\DTLnewdb{TransposedTabularDB}

\NewEnviron{Ttabular}[1]{%
    %\SaveColumnSpecificationAsZ{#1}%
    % Initialize in case of multiple uses
    \setcounter{CurrentColumn}{0}%
    \global\togglefalse{EncounteredDataRow}%
    \savebox{\TempBox}{%
        \begin{tabular}{FCCCCCC}% over speced tabular
            \BODY%
        \end{tabular}%
    }%
    \begin{tabular}{#1}\toprule%
    % This could be made smarter to detect number of columns
    \DTLforeach*{TransposedTabularDB}{\Aa=A, \Ba=B, \Ca=C}{%
      \DTLiffirstrow{}{\\\midrule}%    
        \Aa & \Ba & \Ca %
    }\\\bottomrule%
    \end{tabular}%
}%

\begin{document}
\noindent
\begin{Ttabular}{cccccc}
\bfseries Name & Alice & Bob & Chuck & Dave & Eve\\
\bfseries Sex & Female & Male & Male & Male & Female\\
\bfseries Age & 18 & 19 & 20 & 21 & 22\\
\end{Ttabular}

\bigskip\noindent
Which I want to look like
\bigskip

\noindent
\begin{tabular}{*3c}\toprule
\bfseries Name & \bfseries Sex & \bfseries Age\\\Midrule
Alice & Female & 18\\\midrule
Bob & Male & 19\\\midrule
Chuck & Male & 20\\\midrule
Dave & Male & 21\\\midrule
Eve & Female & 22\\\bottomrule
\end{tabular}
\end{document}

答案4

在回答这个问题时我必须发明这样一种技巧:如何创建接受超过 10 个参数的表宏。但是,这在搜索表转置时永远不会匹配,因此我调整了答案以适应这个更相关的问题,并提供与的兼容性booktabs。它还允许为列和行分隔符自定义输入分隔符。它使用来listofitems解析数据并执行转置到令牌寄存器中。

\documentclass{article}
\usepackage{listofitems,booktabs}
\newtoks\transposedtoks
\newcommand\transposedata[2][\\/&]{%
  \setsepchar{#1}%
  \transposedtoks{\toprule}%
  \greadlist*\rawdata{#2}
  \foreachitem\y\in\rawdata[1]{%
    \foreachitem\x\in\rawdata[]{%
      \ifnum\xcnt>1\transposedtoks\expandafter{\the\transposedtoks&}\fi%
      \expandafter\expandafter\expandafter\def%
        \expandafter\expandafter\expandafter\tmp%
        \expandafter\expandafter\expandafter{%
        \rawdata[\xcnt,\ycnt]}%
      \expandafter\transposedtoks\expandafter\expandafter\expandafter{%
        \expandafter\the\expandafter\transposedtoks\tmp}%
    }%
  \transposedtoks\expandafter{\the\transposedtoks\\}%
  \ifnum\ycnt=\listlen\rawdata[1]\relax\def\tmp{\bottomrule}%
    \else\def\tmp{\midrule}\fi%
  \expandafter\transposedtoks\expandafter\expandafter\expandafter{%
    \expandafter\the\expandafter\transposedtoks\tmp}%
  }%
}
\begin{document}
\transposedata{
\bfseries Name & Alice & Bob & Chuck & Dave & Eve\\
\bfseries Sex & Female & Male & Male & Male & Female\\
\bfseries Age & 18 & 19 & 20 & 21 & 22
}%
\begin{tabular}{*3c}
\the\transposedtoks
\end{tabular}
%
or
%
\transposedata[:/,]{a,b,c:d,e,f}%
\begin{tabular}{*3c}
\the\transposedtoks
\end{tabular}
\end{document}

在此处输入图片描述

相关内容