添加具有相同数据 ID 的列的值?

添加具有相同数据 ID 的列的值?

我想通过添加子日值并生成统一的每日数据,从混合的每日和子日数据中准备统一的每日数据。我的示例输入和所需的输出数据如下所示。

输入文件:

date            Value
01/01/2000     2
01/01/2000     2
01/02/2000     6
01/03/2000     5
01/03/2000     4

所需的输出文件:

date          Value
01/01/2000    4 (i.e. 2+2)
01/02/2000    6
01/03/2000    9(i.e 5+4)

答案1

如果各行按时间顺序排列:

awk '
 NR==1{print;next}
 $1!=l && NR>2{print l,n;n=0}
 {n+=$2;l=$1}
 END{if (NR>1) print l,n}' < input.file > output.file

也就是说,一旦我们看到第一个字段与最后一行不同,就输出计数。这意味着我们不必将所有数据保存在内存中并等到最后才显示它,就像巴伦的或者可持续发展管理解决方案。这也意味着订单会自动保留。

答案2

您可以使用 AWK 及其关联数组来执行此操作:

awk '{ 
    if (NR == 1) { print $0 } 
    else { count[$1] += $2 } 
} 
END { 
    # Sort the items based on the date  
    n = asorti(count, indices)  
    for (i = 1; i <= n; i++) {  
        print indices[i], count[indices[i]]
    }
}' < file_name

当所有记录都处理完毕后,该END块将在最后执行。

数组的排序已从这个帖子

答案3

您可以使用以下awk脚本:

$ awk '
  { a[$1]+=$2 }
  END{ for(val in a) printf("%s %s\n", val, a[val]) }
' <(tail -n +2 sample.txt)

然而,使用这种方法将不再保留输出的顺序。只要数据按日期数字顺序排列,sort最后的简单操作就会重新调整输出。

例子

假设样本数据。

$ cat sample.txt 
date            Value
01/01/2000     2
01/01/2000     2
01/02/2000     6
01/03/2000     5
01/03/2000     4

上述脚本将生成如下结果:

$ awk '
  { a[$1]+=$2 }
  END{ for(val in a) printf("%s %s\n", val, a[val]) }
' <(tail -n +2 sample.txt)
01/02/2000 6
01/01/2000 4
01/03/2000 9

运行输出sort将重新调整数据。

$ awk '
  { a[$1]+=$2 }
  END{ for(val in a) printf("%s %s\n", val, a[val]) }
' <(tail -n +2 sample.txt)|sort
01/01/2000 4
01/02/2000 6
01/03/2000 9

原始文件中的标头可以这样添加回来:

$ (head -n 1 sample.txt; awk '{a[$1]+=$2}END{for(val in a) printf("%s %s\n", val, a[val])}' <(tail -n +2 sample.txt)|sort)
date            Value
01/01/2000 4
01/02/2000 6
01/03/2000 9

您可以将其展开一点,以便更容易阅读:

$ (
head -n 1 sample.txt
awk '
  { a[$1]+=$2 }
  END{ for(val in a) printf("%s %s\n", val, a[val]) }
' <(tail -n +2 sample.txt) | sort
)
date            Value
01/01/2000 4
01/02/2000 6
01/03/2000 9

更新#1

根据评论中 @StephaneChazelas 的反馈,我进一步简化了我的示例。能够通过使用这个()tail ...将其移动到块内来消除 。这将跳过第一行。awkNR==1{ next }sample.txt

我还移动了块| sort内的位置END{...}。这仍然会根据日期重新调整数据sort生成的输出。awk由于awk现在调用/bin/sort它,所以用双引号括起来。

$ awk '
  NR==1{ print; next }
  { a[$1]+=$2 }
    END{ for(val in a) print val, a[val] | "sort" }
' sample.txt
)
date            Value
01/01/2000 4
01/02/2000 6
01/03/2000 9

答案4

我会在 Perl 中这样做:

perl -ane '$.==1 && do{$first=$_; next}; $k{$F[0]}+=$F[1]; END{foreach (keys(%k)){print "$_\t$k{$_}\n"}}' file

01/01/2000  4
01/03/2000  9
01/02/2000  6

这种方法的优点是不需要按时间顺序对行进行排序。

相关内容