用于汇总统计信息的Bash脚本

时间:2012-09-20 18:10:35

标签: bash

我有一个csv客户数据文件,我想知道他们根据过去的行为购买产品的概率。

表格如下:

custId         prodId       purchased
   001           0001          0
   002           0001          0
   006           1001          1
   001           0501          0
   012           8001          0
   189           0071          0
   487           0001          1
   ...           ...          ...

custId是客户ID,prodId是产品,既不是唯一列也不是custId-prodId唯一,因为客户可以多次展示同一产品。

理想的输出类似于:

 custId         purchased
   001           .0999
   002           0
   006           1
   012           0
   189           .75
   487           1
   ...          ...   

我正在考虑在bash中执行此操作,因为文件太大而无法容纳在内存中。

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

由于Jonah Bishop和choroba都在上面评论你应该使用Perl,我倾向于同意,这是一个使用Perl执行此操作的Bash命令:

perl -e \
  ' use warnings;
    use strict;
    my %custCounts;
    my %custSums;
    while(<>)
    {
      m/^(\d{3}),\d{4},([01])$/
        or die "ruakh doesn'"'"'t understand your CSV file format";
      ++$custCounts{$1};
      ++$custSums{$1} if $2;
    }
    foreach my $custId (sort keys %custCounts)
    {
      print "$custId,", ($custSums{$custId}||0) / $custCounts{$custId}, "\n";
    }
  ' < customerData.csv

以上假设您的CSV文件如下所示:

001,0001,0
002,0001,0
006,1001,1
001,0501,0
012,8001,0
189,0071,0
487,0001,1

字段分别为三位数,四位数和01。如果情况并非如此,那么您需要调整以m/开头的行。

答案 1 :(得分:1)

以下是使用awk的简短示例:

awk '{++shown[$1]; if ($3 > 0) ++purchased[$1];}END{for (cust in purchased) print cust, purchased[cust]/shown[cust]}' datafile

没有错误检查,所以如果你的输入偏离,它就会死;此外,您必须预处理以删除任何标题等。如果您的字段分隔符不是空格,请使用'awk -F,...'将字段分隔符设置为','或其他。

此外,这仅打印非零百分比的条目,以包括所有客户,将for (cust in purchased)更改为for (cust in shown)