描述:
我有一个名为namespgf.csv
Reg.No.,Name
5501,Kathirvelu A
5502,Gugan K
5503,Kalaitchelvi S
5504,Suresh S
5505,Mahesh K
另一个名为markspgf.csv
number,marks
5501,67
5502,25
5503,62
5505,95
请注意注册号码 5504 不在markspgf.csv
。
现在我尝试将该marks
列复制到文件中namespgf.csv
并排版如下的表格(这是我想要的):
Reg.No. Name marks
5501 Kathirvelu A 67
5502 Gugan K 25
5503 Kalaitchelvi S 62
5505 Mahesh K 95
这里,考生的注册号5504
在“markspgf.csv”中没有分数。我想从上面的结果表中省略与该号码相对应的条目。但这是我尝试得到的结果:
以下是生成表格的代码(MWE):
\documentclass{article}
\usepackage{pgfplotstable}
\usepackage{filecontents}
%
\begin{filecontents}{namespgf.csv}
Reg.No.,Name
5501,Kathirvelu A
5502,Gugan K
5503,Kalaitchelvi S
5504,Suresh S
5505,Mahesh K
\end{filecontents}
%
\begin{filecontents}{markspgf.csv}
number,marks
5501,67
5502,25
5503,62
5505,95
\end{filecontents}
\begin{document}
%=============================================================================
\pgfplotstableread[col sep=comma]{namespgf.csv}\namespgf
\pgfplotstableread[col sep=comma,verb string type]{markspgf.csv}\markspgf
%
\pgfkeys{/pgfplots/table/verb string type}
% ----------------------------------------------------------------------%
\pgfplotstablecreatecol[copy column from table={\markspgf}{[index] 1},skip first n=1] {marks} {\namespgf}
%
{\centering
\pgfplotstabletypeset[columns={Reg.No.,Name,marks}
]{\namespgf}
}
%
\end{document}
问题:
如何省略与注册号 5504 对应的条目,并在注册号 5505 前面加上正确的标记?(如何获取我上面解释的表格)?
请注意我想要一个使用的解决方案pgfplotstable
。这背后的主要原因是我正在处理的数据量。对于如此大量的数据,datatool
编译需要花费数年时间,有时 pdflatex 会耗尽内存。但pgfplotstable
它速度快,内存效率高。
答案1
编辑请参阅编辑历史以了解不完整的答案。
我所做的是遍历
Reg.No.
条目并尝试查看表number
的列中是否有匹配项\markspgf
。如果有,那么我们marks
在创建新列时使用该行的值,否则我们将输入N/A
.(如果不需要,可以跳过此步骤)。然后,我们记录计数器值,因为\pgfplotstablerow
变量现在不可用,因此我们会跟踪未能匹配的行并增加计数器。
当数字用完后,我们将在新表中使用这个新列,并再次检查每一行是否要使用此行。 如果行号与列表中的第一个数字匹配,我们将触发 if 条件,否则什么也不会\pgfplotsuserowfalse
发生,并且行被排版。
\documentclass{article}
\usepackage{pgfplotstable,xstring}
\usepackage{filecontents,etoolbox}
%
\begin{filecontents}{namespgf.csv}
Reg.No.,Name,Place
5501,Kathirvelu A,re
5502,Gugan K,rt
5503,Kalaitchelvi S,uy
5504,Suresh S,itr
5505,Mahesh K,utyehd
5506,Balini N,utyehd
5507,Kumar H,utyehd
5508,Khalate A,utyehd
5509,me,hgte
5510,you,there
5511,them,here
5512,who,where
\end{filecontents}
%
\begin{filecontents}{markspgf.csv}
number,marks
5501,67
5502,25
5503,62
5505,95
5507,100
5512,45
\end{filecontents}
\def\marksuccess{}
\def\mypopulatedlist{}
\newcounter{myrowcount}
\setcounter{myrowcount}{0}
\begin{document}
%=============================================================================
\pgfplotstableread[col sep=comma]{namespgf.csv}\namespgf
\pgfplotstableread[col sep=comma,verb string type]{markspgf.csv}\markspgf
%
\pgfkeys{/pgfplots/table/verb string type}
% ----------------------------------------------------------------------%
\pgfplotstablecreatecol[
create col/assign/.code={%
\let\marksuccess\relax
\pgfplotstableforeachcolumnelement{number}\of\markspgf\as\cellb{%
\IfStrEq{\thisrow{Reg.No.}}{\cellb}{%True
\pgfplotstablegetelem{\pgfplotstablerow}{marks}\of\markspgf
\edef\myretval{\pgfplotsretval}
\def\marksuccess{1}
%\breakforeach %This would have saved some time if it was available
}
{}%False
}
\if\marksuccess\relax
\def\myretval{N/A}%
\xappto\mypopulatedlist{\arabic{myrowcount},}
\else
\fi
\stepcounter{myrowcount}
\pgfkeyslet{/pgfplots/table/create col/next content}\myretval
}]{Marks}\namespgf
\pgfplotstabletypeset[
column type=l,
columns={Reg.No.,Name,Marks},
row predicate/.code={%
\StrBefore{\mypopulatedlist}{,}[\mynextrow] %Look at the first number before the comma on the list
\IfStrEq{#1}{\mynextrow}{%If the current row is equal to that number
\StrLen{\mynextrow}[\numberlength]%Get the length of the number
\StrGobbleLeft{\mypopulatedlist}{\number\numexpr\numberlength+1\relax}[\mytemplist]%Delete this number and the next comma from the list
\edef\mypopulatedlist{\mytemplist}%Overwrite the old list with the new
\pgfplotstableuserowfalse% Tell pgfplots to omit this row
}{}
}
]\namespgf
\end{document}
答案2
这是一个使用的解决方案包裹datatool
:
笔记:
- 在下面的 MWE 中,我使用了这样
filecontents*
标题filecontents
就不会添加到数据文件中。
代码:
\documentclass{article}
\usepackage{datatool}
\usepackage{xstring}
\usepackage{filecontents}
\begin{filecontents*}{namespgf.csv}
Reg.No.,Name
5501,Kathirvelu A
5502,Gugan K
5503,Kalaitchelvi S
5504,Suresh S
5505,Mahesh K
\end{filecontents*}
%
\begin{filecontents*}{markspgf.csv}
number,marks
5501,67
5502,25
5503,62
5505,95
\end{filecontents*}
%------- Useful for debuging ---------------
\newcommand{\PrintNamesDTLTable}[1]{% #1 = names database
\begin{tabular}{c c}%
Reg No & Name \\\hline%
\DTLforeach{#1}{%
\RegNo=Reg.No.,%
\Name=Name%
}{%
\RegNo & \Name\\%
}%
\end{tabular}%
}%
\newcommand{\PrintMarksDTLTable}[1]{% #1 = marks database
\begin{tabular}{c c}%
Number & Marks \\\hline%
\DTLforeach{#1}{%
\Number=number,%
\Marks=marks%
}{%
\Number & \Marks\\%
}%
\end{tabular}%
}%
%-------------------------------------------
\newcommand*{\PrintIfRegNumberIsInMarks}[3]{%
% #1 = reg number
% #2 = name
% #3 = marks db
%
\DTLforeach{#3}{\Number=number, \Marks=marks}{%
\IfEq{#1}{\Number}{% Found member
#1 & #2 & \Marks \\%
\dtlbreak% Done, break out of loop
}{% Haven't found it yet, so keep looking....
}%
}%
}%
\newcommand{\PrintNamesWithMarksDTLTable}[2]{%
% #1 = names database
% #2 = marks database
\begin{tabular}{c c c}%
Reg No & Name & Marks\\\hline%
\DTLforeach{#1}{%
\RegNo=Reg.No.,%
\Name=Name%
}{%
\PrintIfRegNumberIsInMarks{\RegNo}{\Name}{#2}%
}%
\end{tabular}%
}%
\begin{document}
\DTLloaddb{NamesDB}{namespgf.csv}
%\PrintNamesDTLTable{NamesDB}% Useful for debugging
\DTLloaddb{MarksDB}{markspgf.csv}
%\PrintMarksDTLTable{MarksDB}% Useful for debugging
\PrintNamesWithMarksDTLTable{NamesDB}{MarksDB}
\end{document}
答案3
我知道您只是在寻找pgfplotstable
解决方案,但作为思考的素材,我将添加另一个选项。这使用namespgf.csv
来生成一组键值对。写下标记时,将插入与注册号相对应的名称。我制作了几个包含约 3000 个条目的模拟电子表格(使用数字而不是名称),编译大约需要 15 秒。我不确定pgfplotstable
在效率方面这与解决方案相比如何。请注意,为了简化一些事情,我从数据中删除了标题并手动将它们添加到表中。
\documentclass{article}
\usepackage{xparse}
\usepackage{booktabs}
\usepackage{longtable}
\usepackage{filecontents}
\begin{filecontents*}{namespgf.csv}
5501,Kathirvelu A
5502,Gugan K
5503,Kalaitchelvi S
5504,Suresh S
5505,Mahesh K
\end{filecontents*}
%
\begin{filecontents*}{markspgf.csv}
5501,67
5502,25
5503,62
5505,95
\end{filecontents*}
\ExplSyntaxOn
\tl_new:N \g_tab_rows_tl
\ior_new:N \g_names_ior
\ior_new:N \g_marks_ior
\prop_new:N \g_names_prop
\ior_open:Nn \g_names_ior {namespgf.csv}
\ior_open:Nn \g_marks_ior {markspgf.csv}
\cs_new:Npn \set_name_keys:w #1,#2\q_stop
{
\prop_put:Nnn \g_names_prop {#1} {#2}% reg number is the key and name is the value
}
\cs_new:Npn \tab_write_keys:w #1,#2\q_stop % data from grades sheet
{
\prop_gpop:NnN \g_names_prop {#1} \l_tmpa_tl % pop the name for the reg number
\tl_gput_right:Nn \g_tab_rows_tl {#1&} % number 1st
\tl_gput_right:NV \g_tab_rows_tl \l_tmpa_tl % name 2nd
\tl_gput_right:Nn \g_tab_rows_tl {\\} % grade 3rd
}
\ior_str_map_inline:Nn \g_names_ior
{
\set_name_keys:w #1\q_stop
}
\ior_str_map_inline:Nn \g_marks_ior
{
\tab_write_keys:w #1\q_stop
}
\ior_close:N \g_names_ior
\ior_close:N \g_marks_ior
\NewDocumentCommand { \WriteRows } {}
{
\tl_use:N \g_tab_rows_tl
}
\ExplSyntaxOff
\begin{document}
\begin{longtable}{clc}
Reg.No.&Name&Marks\\
\toprule
\WriteRows
\bottomrule
\end{longtable}
\end{document}