これは次の質問に対するフォローアップです以前のもの。
今回は、2つのケースを取り上げたいと思います。
初め、独自の列ヘッダーと行ヘッダーを適用しながら、テーブルをそのまま読み込みます。
2番テーブルを読み込んで回転し、独自の列ヘッダーと行ヘッダーを適用します。
上記の両方のケースでは、2つの異なるタイプのデータベースが以下のように処理されます。
\documentclass{article}
\usepackage{datatool,filecontents,booktabs}
% 1st dataset
\begin{filecontents*}{data1.csv}
, col1 , col2 , col3
row1 , 11 , 12 , 13
row2 , 21 , 22 , 23
\end{filecontents*}
% 2nd dataset
\begin{filecontents*}{data2.csv}
11 , 12 , 13
21 , 22 , 23
\end{filecontents*}
\begin{document}
\section{First case: without rotation}
The desired output for both datasets should be
\begin{table}[h]
\centering
\caption{without rotation}
\begin{tabular}{@{}lccc@{}}
\toprule
& First Column & Second Column & Third Column\\
\midrule
First Row & 11 & 12 & 13 \\
\midrule
Second Row & 21 & 22 & 23 \\
\bottomrule
\end{tabular}
\end{table}
\section{Second case: with rotation}
The desired output for both datasets should be
\begin{table}[h]
\centering
\caption{with rotation}
\begin{tabular}{@{}lcc@{}}
\toprule
& First Column & Second Column\\
\midrule
First Row & 21 & 11 \\
\midrule
Second Row & 22 & 12 \\
\midrule
Third Row & 23 & 13 \\
\bottomrule
\end{tabular}
\end{table}
\end{document}
答え1
両方のデータベースに同じキーが割り当てられていることを確認することをお勧めします (keys
のオプションを使用\DTLloaddb
)。これは、列インデックスが異なっていても、両方のデータベースで同じ列を参照するためにキーを使用できることを意味します。
\DTLloaddb[keys={rowheader,col1,col2,col3}]{database1}{database1.csv}
\DTLloaddb[noheader,keys={col1,col2,col3}]{database2}{database2.csv}
次のキーを使用して、両方のデータベースの列ヘッダーを設定できます。
\newcommand{\setdatabaseheaders}[1]{%
\DTLsetheader{#1}{col1}{First Column}%
\DTLsetheader{#1}{col2}{Second Column}%
\DTLsetheader{#1}{col3}{Third Column}%
}
\setdatabaseheaders{database1}
\setdatabaseheaders{database2}
etoolbox
ただし、列ヘッダーがすべてのテーブル間で共有されている場合は、のコマンドを使用して、アクセスしやすい方法で列ヘッダーを保存する方が簡単です\csdef
。
\csdef{columnheader1}{First Column}
\csdef{columnheader2}{Second Column}
\csdef{columnheader3}{Third Column}
行ヘッダーの概念はありませんdatatool
が、同様の方法で行インデックスに基づいて行ヘッダーを提供するのは簡単です。
\csdef{rowheader1}{First Row}
\csdef{rowheader2}{Second Row}
で識別される列は、rowheader
データを表示するときに無視する必要があります。この列の存在は で確認できます\DTLifhaskey
。データを表示するためのカスタムコマンドは、 で指定されたコマンドを参照して行ヘッダーを挿入できます。\csname rowheader
idx\endcsname
(または\csuse{rowheader
idx}
) を各行の先頭に追加します。列ヘッダーも同様です。
MWE を完了する:
\documentclass{article}
\usepackage{booktabs}
\usepackage{datatool}
% Case 1
\begin{filecontents*}{database1.csv}
,col1 , col2 , col3
row1 , 11 , 12 , 13
row2 , 21 , 22 , 23
\end{filecontents*}
% Case 2
\begin{filecontents*}{database2.csv}
11 , 12 , 13
21 , 22 , 23
\end{filecontents*}
\DTLloaddb[keys={rowheader,col1,col2,col3}]{database1}{database1.csv}
\DTLloaddb[noheader,keys={col1,col2,col3}]{database2}{database2.csv}
\csdef{rowheader1}{First Row}
\csdef{rowheader2}{Second Row}
\csdef{rowheader3}{Third Row}
\csdef{columnheader1}{First Column}
\csdef{columnheader2}{Second Column}
\csdef{columnheader3}{Third Column}
\newcount\columnidx
\newcount\rowidx
\newcount\columncount
\newcommand{\displaydatabase}[1]{%
\DTLifhaskey{#1}{rowheader}%
{%
\columncount=\numexpr\DTLcolumncount{#1}-1\relax
\def\columnoffset{1}%
}%
{%
\columncount=\DTLcolumncount{#1}%
\def\columnoffset{0}%
}%
% construct \begin{tabular} arguments
\def\columnargs{}%
\columnidx=0
\loop
\advance\columnidx by 1\relax
\appto\columnargs{c}%
\ifnum\columnidx<\columncount
\repeat
\edef\tabularcontents{\noexpand\begin{tabular}{l\columnargs}}%
\appto\tabularcontents{\toprule}%
% add table header
\dtlforeachkey(\thiskey,\thiscol,\thistype,\thisheader)\in#1\do
{%
\ifdefstring{\thiskey}{rowheader}%
{}%
{%
\eappto\tabularcontents{\noexpand&
\expandonce{\csname columnheader\number\numexpr\thiscol-\columnoffset\endcsname}}%
}%
}%
% iterate over all rows
\rowidx=0
\loop
\advance\rowidx by 1\relax
% header
\eappto\tabularcontents{\noexpand\\\noexpand\midrule
\expandonce{\csname rowheader\the\rowidx\endcsname}}%
% columns
\dtlforeachkey(\thiskey,\thiscol,\thistype,\thisheader)\in#1\do
{%
\ifdefstring{\thiskey}{rowheader}%
{}%
{%
\DTLgetvalue{\thisvalue}{#1}{\rowidx}{\thiscol}%
\eappto\tabularcontents{\noexpand& \expandonce\thisvalue}%
}%
}%
\ifnum\rowidx<\DTLrowcount{#1}
\repeat
\appto\tabularcontents{\\\bottomrule\end{tabular}}%
\tabularcontents
}
\newcommand{\displayrotateddatabase}[1]{%
\DTLifhaskey{#1}{rowheader}%
{%
\def\columnoffset{1}%
}%
{%
\def\columnoffset{0}%
}%
\columncount=\DTLrowcount{#1}%
% construct \begin{tabular} arguments
\def\columnargs{}%
\columnidx=0
\loop
\advance\columnidx by 1\relax
\appto\columnargs{c}%
\ifnum\columnidx<\columncount
\repeat
\edef\tabularcontents{\noexpand\begin{tabular}{l\columnargs}}%
\appto\tabularcontents{\toprule}%
% add table header
\columnidx=0
\loop
\advance\columnidx by 1\relax
\eappto\tabularcontents{\noexpand&
\expandonce{\csname columnheader\the\columnidx\endcsname}}%
\ifnum\columnidx<\columncount
\repeat
% iterate through all columns omitting rowheader
\dtlforeachkey(\thiskey,\thiscol,\thistype,\thisheader)\in#1\do
{%
\ifdefstring{\thiskey}{rowheader}%
{}%
{%
% header title
\eappto\tabularcontents{%
\noexpand\\\noexpand\midrule
\expandonce{\csname rowheader\number\numexpr\thiscol-\columnoffset\endcsname}}%
% row loop in reverse order
\rowidx=\DTLrowcount{#1}\relax
\loop
\DTLgetvalue{\thisvalue}{#1}{\rowidx}{\thiscol}%
\eappto\tabularcontents{\noexpand&\expandonce\thisvalue}%
\advance\rowidx by -1\relax
\ifnum\rowidx>0
\repeat
}%
}%
\appto\tabularcontents{\\\bottomrule\end{tabular}}%
\tabularcontents
}
\newcommand{\displaytransposedatabase}[1]{%
\DTLifhaskey{#1}{rowheader}%
{%
\def\columnoffset{1}%
}%
{%
\def\columnoffset{0}%
}%
\columncount=\DTLrowcount{#1}%
% construct \begin{tabular} arguments
\def\columnargs{}%
\columnidx=0
\loop
\advance\columnidx by 1\relax
\appto\columnargs{c}%
\ifnum\columnidx<\columncount
\repeat
\edef\tabularcontents{\noexpand\begin{tabular}{l\columnargs}}%
\appto\tabularcontents{\toprule}%
% add table header
\columnidx=0
\loop
\advance\columnidx by 1\relax
\eappto\tabularcontents{\noexpand&
\expandonce{\csname columnheader\the\columnidx\endcsname}}%
\ifnum\columnidx<\columncount
\repeat
% iterate through all columns omitting rowheader
\dtlforeachkey(\thiskey,\thiscol,\thistype,\thisheader)\in#1\do
{%
\ifdefstring{\thiskey}{rowheader}%
{}%
{%
% header title
\eappto\tabularcontents{%
\noexpand\\\noexpand\midrule
\expandonce{\csname rowheader\number\numexpr\thiscol-\columnoffset\endcsname}}%
% row loop
\rowidx=0\relax
\loop
\advance\rowidx by 1\relax
\DTLgetvalue{\thisvalue}{#1}{\rowidx}{\thiscol}%
\eappto\tabularcontents{\noexpand&\expandonce\thisvalue}%
\ifnum\rowidx<\DTLrowcount{#1}
\repeat
}%
}%
\appto\tabularcontents{\\\bottomrule\end{tabular}}%
\tabularcontents
}
\begin{document}
\section{No rotation}
\subsection{database1}
\displaydatabase{database1}
\subsection{database2}
\displaydatabase{database2}
\subsection{Desired Output}
\begin{table}[h]
\centering
\caption{without rotation}
\begin{tabular}{@{}lccc@{}}
\toprule
& First Column & Second Column & Third Column\\
\midrule
First Row & 11 & 12 & 13 \\
\midrule
Second Row & 21 & 22 & 23 \\
\bottomrule
\end{tabular}
\end{table}
\newpage
\section{Rotation}
\subsection{database1}
\displayrotateddatabase{database1}
\subsection{database2}
\displayrotateddatabase{database2}
\subsection{Desired Output}
\begin{table}[h]
\centering
\caption{with rotation}
\begin{tabular}{@{}lcc@{}}
\toprule
& First Column & Second Column\\
\midrule
First Row & 21 & 11 \\
\midrule
Second Row & 22 & 12 \\
\midrule
Third Row & 23 & 13 \\
\bottomrule
\end{tabular}
\end{table}
\newpage
\section{Transpose}
\subsection{database1}
\displaytransposedatabase{database1}
\subsection{database2}
\displaytransposedatabase{database2}
\end{document}
回転されていないテーブル:
回転したテーブル:
転置されたテーブル:
ノート:
\DTLloaddb
は末尾のスペースを削除しないので、 を使用しなかった場合keys={rowheader,col1,col2,col3}
、2 列目、3 列目、4 列目のキーには末尾のスペースが含まれます。次の MWE は機能しません。\documentclass{article} \usepackage{datatool} \begin{filecontents*}{database1.csv} ,col1 , col2 , col3 row1 , 11 , 12 , 13 row2 , 21 , 22 , 23 \end{filecontents*} \DTLloaddb{database1}{database1.csv} \DTLsetheader{database1}{col1}{First Column} \begin{document} \end{document}
これによりエラーが発生します
! Package datatool Error: Database `database1' doesn't contain key `col1'.
列ラベルには末尾のスペースが含まれるため、割り当ては次のようになります。
\DTLsetheader{database1}{col1 }{First Column}
先頭のスペースは無視されるので、
\DTLsetheader{database1}{ col2 }{Second Column}
CSV ファイルの先頭にスペースがあっても、エラーが発生します。次のようになります。
\DTLsetheader{database1}{col2 }{Second Column}
各エントリについても同様です。例:
\documentclass{article}
\usepackage{datatool}
\begin{filecontents*}{database1.csv}
,col1 , col2 , col3
row1 , 11 , 12 , 13
row2 , 21 , 22 , 23
\end{filecontents*}
\DTLloaddb{database1}{database1.csv}
\begin{document}
\DTLgetvalue{\thisvalue}{database1}{1}{2}`\thisvalue'.
\end{document}
これにより、次のものが生成されます。
先頭のスペースは無視されますが、末尾のスペースは保持されます。
keys
この例では、スペースを含まない を使用してキーが割り当てられているため、大きな違いはありません。エントリはtabular
環境内にあるため、不要なスペースは目立ちませんが、注意が必要です。