Bash 使用awk进行无需更换的采样
我有很多这样的文本文件:Bash 使用awk进行无需更换的采样,bash,shell,awk,Bash,Shell,Awk,我有很多这样的文本文件: >ALGKAHOLAGGATACCATAGATGGCACGCCCT >BLGKAHOLAGGATACCATAGATGGCACGCCCT >HLGKAHOLAGGATACCATAGATGGCACGCCCT >DLGKAHOLAGGATACCATAGATGGCACGCCCT >ELGKAHOLAGGATACCATAGATGGCACGCCCT >FLGKAHOLAGGATACCATAGATGGCACGCCCT >JGGKAHOLAGG
>ALGKAHOLAGGATACCATAGATGGCACGCCCT
>BLGKAHOLAGGATACCATAGATGGCACGCCCT
>HLGKAHOLAGGATACCATAGATGGCACGCCCT
>DLGKAHOLAGGATACCATAGATGGCACGCCCT
>ELGKAHOLAGGATACCATAGATGGCACGCCCT
>FLGKAHOLAGGATACCATAGATGGCACGCCCT
>JGGKAHOLAGGATACCATAGATGGCACGCCCT
>POGKAHOLAGGATACCATAGATGGCACGCCCT
>FLGKAHOLAGGATACCATAGATGGCACGCCCT
>POGKAHOLAGGATACCATAGATGGCACGCCCT
>ALGKAHOLAGGATACCATAGATGGCACGCCCT
>BLGKAHOLAGGATACCATAGATGGCACGCCCT
有没有一种不用awk进行更换的采样方法
例如,我有这8行代码,我只想在一个新文件中随机抽取其中的4行,而不需要替换。
输出应如下所示:
>ALGKAHOLAGGATACCATAGATGGCACGCCCT
>BLGKAHOLAGGATACCATAGATGGCACGCCCT
>HLGKAHOLAGGATACCATAGATGGCACGCCCT
>DLGKAHOLAGGATACCATAGATGGCACGCCCT
>ELGKAHOLAGGATACCATAGATGGCACGCCCT
>FLGKAHOLAGGATACCATAGATGGCACGCCCT
>JGGKAHOLAGGATACCATAGATGGCACGCCCT
>POGKAHOLAGGATACCATAGATGGCACGCCCT
>FLGKAHOLAGGATACCATAGATGGCACGCCCT
>POGKAHOLAGGATACCATAGATGGCACGCCCT
>ALGKAHOLAGGATACCATAGATGGCACGCCCT
>BLGKAHOLAGGATACCATAGATGGCACGCCCT
提前感谢对你10%的线路进行随机抽样怎么样
awk 'rand()>0.9' yourfile1 yourfile2 anotherfile
我不知道你说的“替换”是什么意思。。。这里没有替换,只是随机选择
基本上,它会精确地查看每个文件的每一行,并在0到1之间生成一个随机数。如果随机数大于0.9,则输出该行。因此,基本上它是为每行滚动一个10面骰子,并且只有当骰子显示为10时才打印它。一行不可能被打印两次——当然,除非它在您的文件中出现两次
为了增加随机性(!),您可以按照@klashxx的建议,在开始处添加一个srand()
awk 'BEGIN{srand()} rand()>0.9' yourfile(s)
是的,但我不会。我会使用
shuf
或sort-R
(两者都不是POSIX)对文件进行随机化,然后使用head
选择第一行n
如果您真的想使用
awk
,您需要使用rand
函数,正如Mark Setchell指出的那样。也许最好使用固定模式对文件进行采样,比如每10行采样一条记录。您可以使用此awk
一行程序执行此操作:
awk '0==NR%10' filename
如果您想对总数的某个百分比进行采样,那么您可以编程一种方法来计算awk
一行应该使用的行数,以便打印的记录数与该数量/百分比相匹配
我希望这有帮助 从文本文件中获取随机样本而不进行替换,意味着一旦随机选择(采样)了一行,就不能再选择它。因此,如果要选择100行中的10行,则十个随机行号必须是唯一的 下面是一个脚本,用于从文本
文件生成NUM
随机(不替换)样本:
#!/usr/bin/env bash
# random-samples.sh NUM FILE
# extract NUM random (without replacement) lines from FILE
num=$(( 10#${1:?'Missing sample size'} ))
file="${2:?'Missing file to sample'}"
lines=`wc -l <$file` # max num of lines in the file
# get_sample MAX
#
# get a random number between 1 .. max
# (see the bash man page on RANDOM
get_sample() {
local max="$1"
local rand=$(( ((max * RANDOM) / 32767) + 1 ))
echo "$rand"
}
# select_line LINE FILE
#
# select line LINE from FILE
select_line() {
head -n $1 $2 | tail -1
}
declare -A samples # keep track of samples
for ((i=1; i<=num; i++)) ; do
sample=
while [[ -z "$sample" ]]; do
sample=`get_sample $lines` # get a new sample
if [[ -n "${samples[$sample]}" ]]; then # already used?
sample= # yes, go again
else
(( samples[$sample]=1 )) # new sample, track it
fi
done
line=`select_line $sample $file` # fetch the sampled line
printf "%2d: %s\n" $i "$line"
done
exit
你说的重采样是什么意思?对不起,这是一个打字错误,我的意思是“采样而不替换”。我要编辑它。谢谢。你说的“不替换采样”是什么意思?示例输出是什么样子的,为什么?嗯。。。那么“抽样”是什么意思?是否要从文件中删除重复的行?您想删除每个文件中的重复项还是所有文件中的重复项?我不熟悉shuf
,但是sort-R
将创建一个与原始文件一样大的文件对象(在磁盘上,或者在内存中,如果通过管道),这对于大文件可能会有问题。@cmh我确信shuf
也会这样做。但是,虽然OP说他有几个文件,但他并没有说这些文件很大。@kojiro,当然,这只是未来考虑使用大文件的这种方法的任何人的一个脚注。不需要head-n4 | shuf
,您可以使用shuf-n4
很好的解决方案,我会添加一个对srand的调用,以便“获取真正不可预测的随机数。”awk'BEGIN{srand()}rand()>0.9'不,如果你按照我说的方式来做,你的开场白是不正确的。基本上,它会精确地查看每个文件的每一行,并在0到1之间生成一个随机数。如果随机数大于0.9,则输出该行。因此,基本上,它是为每一行滚动一个10面骰子,并且只有在骰子出现时才打印它们这是10。一行不可能被打印两次。@Mark Setchell哦,我明白了。谢谢你的澄清。我已经编辑了我的答案,所以没有误解。但是,由于随机是随机的(D'Oh!),所以可能所有的都是随机的(也就是整个文件)得到打印…或者没有一个得到打印…这就是为什么我给出了一个不依赖于随机性的想法,而是取决于你想要输出的记录的数量。