에 대한 후속 질문입니다.내 이전 것.
이번 경우에는 다음 두 가지 경우를 다루고 싶습니다.
첫 번째, 열과 행 머리글을 직접 적용하면서 테이블을 그대로 로드합니다.
두번째, 테이블을 로드하고 회전한 다음 나만의 열 및 행 헤더를 적용합니다.
위에서 언급한 두 경우 모두 아래와 같이 서로 다른 두 가지 유형의 데이터베이스가 처리됩니다.
\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}
두 번째, 세 번째 및 네 번째 열의 키에 후행 공백이 포함됩니다. 다음 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
환경에 있으므로 가짜 공간이 눈에 띄지 않지만 주의해야 할 부분입니다.