![随机采样并输出最大值](https://linux22.com/image/69096/%E9%9A%8F%E6%9C%BA%E9%87%87%E6%A0%B7%E5%B9%B6%E8%BE%93%E5%87%BA%E6%9C%80%E5%A4%A7%E5%80%BC.png)
我有一个相当大的数据集~5亿行。数据集如下所示。第 1 列是浮点数,第 2 列是 mac id(设备 id)
1616.93,ac:22:0b:a6:22:c3
2872.32,c0:bd:d1:36:bb:49
3314.55,d4:0b:1a:39:19:b2
2854.11,18:f6:43:64:81:67
3540.68,18:f6:43:64:81:67
3856.91,ac:22:0b:a6:22:c3
2497.93,d4:0b:1a:39:19:b2
该问题需要在对第 2 列进行分组后输出约 100,000 个随机样本,然后从该特定组的第 1 列中找到最大值。
中间输出如下所示(group by col1 ):
1616.93,ac:22:0b:a6:22:c3
3856.91,ac:22:0b:a6:22:c3
2854.11,18:f6:43:64:81:67
3540.68,18:f6:43:64:81:67
2872.32,c0:bd:d1:36:bb:49
3314.55,d4:0b:1a:39:19:b2
2497.93,d4:0b:1a:39:19:b2
之后,我需要每个分组的列中的最大值。输出如下所示:
3856.91,ac:22:0b:a6:22:c3
3540.68,18:f6:43:64:81:67
2872.32,c0:bd:d1:36:bb:49
3314.55,d4:0b:1a:39:19:b2
最后一步是获得真正的随机样本,输出如下所示:
3540.68,18:f6:43:64:81:67
2872.32,c0:bd:d1:36:bb:49
任何想法,如何执行此操作。我刚刚开始使用 Linux,不知道如何执行如此艰巨的任务。任何帮助,将不胜感激。
答案1
尝试
BEGIN { srand() ;r=0 ; FS="," ; before="" ; }
{ if ( $1 > V[$2]) V[$2]=$1 ;
if ( before != $2 && before != "" ) {
r=rand()*100 ;
if ( r > 50 ) printf "%s,%s\n",V[before],before ;
}
before=$2 ;
} data-file.txt
在哪里
if ( $1 > V[$2]) V[$2]=$1
;获取 mac 的最大值if ( before != $2 && before != "" ) {
当新的 mac 值出现时r=rand()*100 ; if ( r > 50 ) printf "%s,%s\n",V[before],before ;
计算一个随机值,如果超过 50% 则打印(可以更改为 5% 或 95%)
答案2
5 亿行是大量数据,因此您可能希望寻找一种更具可扩展性的方式来处理这项工作。也就是说,使用标准 Linux 实用程序来完成此操作是可以实现的。
假设您的数据位于名为的文件中,data.txt
您可以使用以下命令将其打印到终端cat
:
$ cat data.txt
1616.93,ac:22:0b:a6:22:c3
2872.32,c0:bd:d1:36:bb:49
3314.55,d4:0b:1a:39:19:b2
2854.11,18:f6:43:64:81:67
3540.68,18:f6:43:64:81:67
3856.91,ac:22:0b:a6:22:c3
2497.93,d4:0b:1a:39:19:b2
sort
然后可以使用选项将该输出通过管道传送到其中-t ',' -k 2
。这些选项将指示sort
使用逗号作为分隔符来分割数据,然后按第二列中的值进行排序:
$ cat data.txt | sort -t ',' -k 2
2854.11,18:f6:43:64:81:67
3540.68,18:f6:43:64:81:67
1616.93,ac:22:0b:a6:22:c3
3856.91,ac:22:0b:a6:22:c3
2872.32,c0:bd:d1:36:bb:49
2497.93,d4:0b:1a:39:19:b2
3314.55,d4:0b:1a:39:19:b2
对于您的下一个任务,您将需要使用sort
选项-t ',' -k 1 -r
。这将使用逗号作为分隔符和第一列中的值进行排序。将按-r
尊敬的顺序排序,首先给出最大的条目:
$ cat data.txt | sort -t ',' -k 1 -r
3856.91,ac:22:0b:a6:22:c3
3540.68,18:f6:43:64:81:67
3314.55,d4:0b:1a:39:19:b2
2872.32,c0:bd:d1:36:bb:49
2854.11,18:f6:43:64:81:67
2497.93,d4:0b:1a:39:19:b2
1616.93,ac:22:0b:a6:22:c3
然后,您需要sort
再次将上述示例的输出通过管道传输到其中,这次使用-t ',' -k 2 -u
选项。和以前一样-t ','
,-k 2
告诉 sort 使用第二列,而新选项-u
告诉 sort 仅保留唯一的条目。
因为我们已按第一列中的值对数据进行排序,所以在查找唯一条目时,将首先找到最高的条目。这将为我们提供每个 MAC 地址的单个最高值:
$ cat data.txt | sort -t ',' -k 1 -r | sort -t ',' -k 2 -u
3540.68,18:f6:43:64:81:67
3856.91,ac:22:0b:a6:22:c3
2872.32,c0:bd:d1:36:bb:49
3314.55,d4:0b:1a:39:19:b2
最后,要获得随机样本,您可以使用shuf
以下选项-n 2
,其中 2 是您想要的随机样本数量:
$ shuf data.txt -n 2
3856.91,ac:22:0b:a6:22:c3
3314.55,d4:0b:1a:39:19:b2
答案3
供记录。这似乎有效,其他选项均无效
sort -t "," -k2,2 -k1,1 -r output.txt| awk -F "," '!a[$2]++'|head -100