我正在寻找有关如何在 1 行 AWK 命令不再足够的情况下操作数据的建议。我正在处理多达 1000 多个行和列的数据集。我遇到了定义太多列变量的问题。我认为有一种方法可以使用循环来迭代数组,以可能定义我要计数和求和的列。我正在尝试根据类似于 Excel COUNTIF 和 SUMIF 的键值计算行的计数和总和。
Data Set Example:
Store_Location;Person;Adult_Child;Age;Weight...
LocationA;PersonA;0;50;200
LocationB;PersonB;1;10;100
LocationA;PersonC;1;12;90
LocationA;PersonA;0;50;200
Desired Output: (delimiter is not important)
Store_Location;Count_Of_Adults;Count_of_Children;Sum_of_Age;Sum_of_Weight
LocationA;2;1;112;490
LocationB;0;1;10;100
这是我使用的 AWK 脚本示例:
BEGIN {FS=";"} {print "Store_Location;Count_Of_Adults;Count_of_Children;Sum_of_Age;Sum_of_Weight"}
{
n[$1]++;
C1_[$1] += ($3 == "1" ? 0 : 1);S1_[$1] += $4;column_sum3+=$4
C2_[$1] += ($3 == "0" ? 0 : 1);S2_[$1] += $5;column_sum4+=$5
}
END {
for (i in n) {
print i,C1_[i],C2_[i],S1_[i],S2_[i]
}
}
我使用a2p将语法转换为perl并做了一些修改(基于使用不同的列):
$base = 20;
while (<>){
@array = split(/$FS/, $_, -1);
$n{$array[$base]}++;
$C1_{$array[$base]} += ($array[21] eq '' ? 0 : 1);
$C2_{$array[$base]} += ($array[34] eq '' ? 0 : 1);
$column_count1 += ($array[21] eq '' ? 0 : 1);
$column_count2 += ($array[34] eq '' ? 0 : 1);
$S1_{$array[$base]} += $array[21];
$S2_{$array[$base]} += $array[34];
$column_sum1 += $array[21];
$column_sum2 += $array[34];
}
@sorted_keys = sort { $a <=> $b} keys %n;
foreach $i (@sorted_keys){
print $i,$C1_{$i},$C2_{$i},$S1_{$i},$S2_{$i};
我希望能够做类似的事情,但我试图将我想要求和的列和我想要计数的列放入不同的数组中。例如:@sum_array=[1,6,10,15,30] & @count_array = [1,10,20]。并使用循环创建总和和计数,而无需声明每个输出列。我可以对每一列进行求和和计数,然后打印我需要的列。我在尝试使用散列/数组在 Perl 中编写此代码时遇到了困难。我尝试使用哈希,但无法获得输出格式,因此我不确定这是否是我想要的数据结构。
$n{$array[$base]}{Adult}{count}+= ($array[21] eq 0 ? 0 : 1);
$n{$array[$base]}{Child}{count}+= ($array[21] eq 1 ? 0 : 1);
$n{$array[$base]}{Weight}{sum} += $array[21];
$n{$array[$base]}{Age}{sum}+= $array[34];
编辑: 我认为我的逻辑问题是我不想调用字段名称/列。因为我想对许多字段执行求和和计数。成人 child 比较只是一个例子。我只想在一处列出我想要使用的列。也许解释它的简单方法是,假设输入数据有 100 列。我希望能够灵活地识别我想要分析的列。例如:第 15-30 列我想根据第 1 列中的唯一值获取每列的总和和计数。然后能够修改相同的代码以获取第 15-20 列和 30-40 列的总和。使用 AWK,我可以调出我想要使用的列($2、$3、$4,...),但当列太多时,管理会变得困难。
最佳答案
尚不完全清楚您想要什么,当然也不清楚您所说的“我在定义太多列变量时遇到问题”是什么意思,但这就是我认为您正在尝试做的事情,希望它能让您继续前进走在正确的道路上:
$ cat file
Store_Location;Person;Adult_Child;Age;Weight
LocationA;PersonA;0;50;200
LocationB;PersonB;1;10;100
LocationA;PersonC;1;12;90
LocationA;PersonA;0;50;200
$ cat tst.awk
BEGIN{ FS=OFS=";" }
NR==1 {
split($0,nr2nm)
for (nr=1;nr in nr2nm;nr++) {
nm2nr[nr2nm[nr]] = nr
}
next
}
{
stores[$nm2nr["Store_Location"]]
for (nr=3; nr<=NF; nr++) {
fldName = nr2nm[nr]
if ( fldName == "Adult_Child" ) {
fldName = ($nr == 1 ? "Child" : "Adult")
}
fldNames[fldName]
cnt[$nm2nr["Store_Location"],fldName]++
sum[$nm2nr["Store_Location"],fldName] += $nr
}
}
END {
printf "%s", "Store_Location"
for (fldName in fldNames) {
printf ";cnt[%s];sum[%s]", fldName, fldName
}
print ""
for (store in stores) {
printf "%s", store
for (fldName in fldNames) {
printf ";%d;%d", cnt[store,fldName], sum[store,fldName]
}
print ""
}
}
$ awk -f tst.awk file
Store_Location;cnt[Weight];sum[Weight];cnt[Child];sum[Child];cnt[Adult];sum[Adult];cnt[Age];sum[Age]
LocationA;3;490;1;1;2;0;3;112
LocationB;1;100;1;1;0;0;1;10
关于perl - 利用 Perl 操作 csv/分号数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19985805/