将(rbind)多个大型csv文件合并为一个具有不同列顺序的文件

时间:2018-02-14 18:04:01

标签: r linux bash shell awk

我在一个文件夹中有多个大型csv文件,我正在尝试将它们rbind(连接)成一个csv。但是,在执行此操作时,我希望确保连接后所有列值都在适当的列中。由于内存限制,我无法在R中执行此操作。我对shell脚本非常陌生,我知道如果不将所有csv文件都放入内存中,可能会有一些方法可以做到这一点。

例如

> csv1
     A  B  C  D  E
     1  2  4  5  6
     4  5  7  8  9
     3  5  6  7  8
     2  3  4  5  8

> csv1
    C  B  E  D  A
    10 22 43 35 66
    14 15 37 48 99
    33 25 56 67 88

> Desired Output
         A  B  C  D  E
         1  2  4  5  6
         4  5  7  8  9
         3  5  6  7  8
         2  3  4  5  8
        66 22 10 35 43
        99 15 14 48 37
        88 25 33 67 56

我的尝试:

我尝试在保存时为每个文件设置R中的列顺序,然后使用下面的代码进行连接。我想知道一种方法,我可以在linux shell中做所有事情。

nawk 'FNR==1 && NR!=1{next;}{print}' *.csv > result.csv

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

由于我没有大数据,因此无法对其进行测试。你可以尝试一次,让我知道这是否对你有帮助。

解决方案1: 每次检查并注明字段的数字,然后在所有传递的Input_file中打印它们:

awk '
FNR==NR && FNR==1{
  for(i=1;i<=NF;i++){
      b[i]=$i};
  print;
  i--;
  next
}
FNR==NR{
  print;
  next
}
FNR!=NR && FNR==1{
  for(j=1;j<=NF;j++){
      c[$j]=j};
  next
}
FNR!=NR && FNR>1{
  for(k=1;k<=i;k++){
      printf("%s%s",$c[b[k]],k==i?RS:FS)}
}
'  csv1 csv2

输出如下:

A  B  C  D  E
1  2  4  5  6
4  5  7  8  9
3  5  6  7  8
2  3  4  5  8
66 22 10 35 43
99 15 14 48 37
88 25 33 67 56

解决方案第二: 检查OP和OP是否可以按列排序格式打印数据,因此我们无需记下该字段所有Input_file中的每次序列号(也考虑到所有传递的Input_file中的字段都相同),我相信与以前的解决方案相比可能更快:

awk '
BEGIN{
  PROCINFO["sorted_in"] = "@ind_num_asc"
}
FNR==1{
  for(i=1;i<=NF;i++){
     a[$i]=i};
  if(FNR==1 && FNR==NR){
     print};
  next
}
{
  for(j in a){
     printf("%s ",$a[j])}
  print ""
}
' csv1 csv2

答案 1 :(得分:2)

另一个类似的awk

$ awk 'NR==1   {split($0,t)} 
       NR==FNR {print; next}  
       FNR==1  {for(i=1;i<=NF;i++) k[$i]=i; next}
               {for(i=1;i<=NF;i++) 
                   printf("%s%s", $(k[t[i]]), (i==NF?ORS:OFS))}' file1 file2 | column -t

A   B   C   D   E
1   2   4   5   6
4   5   7   8   9
3   5   6   7   8
2   3   4   5   8
66  22  10  35  43
99  15  14  48  37
88  25  33  67  56

使用第一个文件中列标题的顺序。假设匹配列数......