Bash 从各组中提取N

Bash 从各组中提取N,bash,awk,sed,split,Bash,Awk,Sed,Split,我有一个csv文件,有两列:“id”和“值” id可以在文件中以不同的值出现多次。我想对数据进行分层抽样,以获得一个较小的文件,该文件正好包含,或者最多包含N个id [akshay@localhost tmp]$ awk -v n=2 '++arr_seen[$1] <=n' file a 1,2,3 a 2,2,3 b 3,4,4 b 8,8,8 c 4,5,6 c 5,5,4 输入示例: a

我有一个csv文件,有两列:“id”和“值”

id可以在文件中以不同的值出现多次。我想对数据进行分层抽样,以获得一个较小的文件,该文件正好包含,或者最多包含N个id

[akshay@localhost tmp]$ awk -v n=2 '++arr_seen[$1] <=n'  file
    a    1,2,3
    a    2,2,3
    b    3,4,4
    b    8,8,8
    c    4,5,6
    c    5,5,4
输入示例:

    a    1,2,3
    a    2,2,3
    a    2,2,3
    a    2,4,3
    a    4,2,3
    a    4,4,4
    b    3,4,4
    b    8,8,8
    b    3,3,3
    c    4,5,6
    c    5,5,4
期望输出N=2:

    a    1,2,3
    a    2,2,3
    b    3,4,4
    b    8,8,8
    c    4,5,6
    c    5,5,4
在这一点上,我不关心从一个组的id是采取,但奖金点,如果它是随机的


由于文本文件可能非常大,我更喜欢内存高效的linux命令行解决方案,即bash、awk、sed等。

根据@Sundeep的建议,我使用shuf和awk以及数组[id]计数结构为N=10制作了一个解决方案:

shuf ./data.csv | awk '{count[$1]++} {if (count[$1] < 10)print $1, $2}' ./data.csv 
这将获取每个id的前10项

[akshay@localhost tmp]$ awk -v n=2 '++arr_seen[$1] <=n'  file
    a    1,2,3
    a    2,2,3
    b    3,4,4
    b    8,8,8
    c    4,5,6
    c    5,5,4
简要说明

n=2:将所需的显示时间设置为bash变量n
arr[$1]这里是awk中的一个,实现某种随机性。它读取文件两次。在第一轮中,它计数键,在第二轮中,它以某种概率输出记录。未进行广泛测试,但应避免被零除,如果概率之神在此之前未干预,则返回每个密钥的最后2条记录:

$ awk -v seed=$RANDOM -v n=2 '  # n is the count of keys wanted
BEGIN {
    srand(seed)                 
}
NR==FNR {                       # on the first run
    nc[$1]=n                    # ncound for each key (2)
    c[$1]++                     # count of keys
    next
}
{
    if(nc[$1]>0 && c[$1]>0 && (nc[$1]/c[$1]/(1-rand()))>1) {
        print
        nc[$1]--                # reduce n count for key when printing
    }
    c[$1]--                     # keys left counter reduces at each iteration
}' file file
a    1,2,3
a    4,2,3
b    8,8,8
b    3,3,3
c    4,5,6
c    5,5,4
另一次运行产生:

a    2,2,3
a    4,2,3
b    3,4,4
b    8,8,8
c    4,5,6
c    5,5,4

nc[$1]/c[$1]/1-rand>1这保证了如果之前没有打印任何记录,则返回每个键的2个或n个最后记录,例如nc=2;c=2,则nc/c==1和1/[0-1[>1始终。rand返回范围为[0-1]的值[为了避免/0,存在/1-随机分布,但可能不均匀。

请添加您试图解决此问题的内容…使用awk,您可以使用id作为密钥的数组,如果该密钥最多被看到N次,则可以打印感谢提示,我对awk不是很熟悉。我使用您的建议创建了一个解决方案。对于随机,您可以使用ng like shuf data.csv | awk-v n='2''++seed[$1]很好的答案,并且能够使用种子使其可复制,这是非常棒的。但是,对我的案例来说,重复两次文件会使其不太实用。
a    2,2,3
a    4,2,3
b    3,4,4
b    8,8,8
c    4,5,6
c    5,5,4