根据第一列中的唯一元素,它不是制作一个脚本,而是根据一个大的制表符分隔文本文件。这意味着,对于第一列中的每个唯一元素,行数将相等并由用户指定。
有两种输出可能性,维持行顺序或随机行顺序。
输入:
chr1 3003204 3003454 * 37 +
chr1 3003235 3003485 * 37 +
chr1 3003148 3003152 * 37 -
chr1 3003461 3003711 * 37 +
chr11 71863609 71863647 * 37 +
chr11 71864025 71864275 * 37 +
chr11 71864058 71864308 * 37 -
chr11 71864534 71864784 * 37 +
chrY 90828920 90829170 * 23 -
chrY 90829096 90829346 * 23 +
chrY 90828924 90829174 * 23 -
chrY 90828925 90829175 * 23 -
输出(每个类别1行 - 由用户定义) Output1(随机 - 行顺序将改变):
chr1 3003235 3003485 * 37 +
chr11 71863609 71863647 * 37 +
chrY 90828925 90829175 * 23 -
输出1(随机 - 将保留行顺序):
chr1 3003204 3003454 * 37 +
chr11 71863609 71863647 * 37 +
chrY 90828920 90829170 * 23 -
我尝试在第一列使用sort -u
cut
来获取唯一元素,然后为每个元素运行grep
和head
的组合以生成输出文件,可以使用shuf
随机化,可能有更好的解决方案,因为文件可能很大> 5000万行。
干杯
答案 0 :(得分:1)
当然,编写脚本会更容易吗?
perl -n -e 'BEGIN{ %c=qw(chr1 4 chr11 4 chrY 4); $c{$_}=int(rand($c{$_})) for keys %c; $r="^(".join("|",keys %c).")\\s";} print if (/$r/o and !$c{$1}--);' filename.txt
脚本启动时执行一次BEGIN块。 print if..
语句用于文件
%c关联数组具有要查找的键和每个键的项数
$ r是一个看似^(chr1|chr11|chrY)\s
如果找到正则表达式,则匹配中的匹配键将用作对递减的关联数组的查找。当它为零时,打印行
答案 1 :(得分:1)
尝试使用awk
维护行顺序
awk '!($1 in a) {a[$1]=$0} END { asort(a,b); for (x in b) print b[x] }' file
输出:
chr1 3003204 3003454 * 37 +
chr11 71863609 71863647 * 37 +
chrY 90828920 90829170 * 23 -
随机排序
为此,只需将 shuf 的输出管道输出到上面的 awk 命令
shuf file | awk '!($1 in a) {a[$1]=$0} END { asort(a,b); for (x in b) print b[x] }'
输出(每次运行都不同)
chr1 3003148 3003152 * 37 -
chr11 71864025 71864275 * 37 +
chrY 90829096 90829346 * 23 +
可变行数
#!/bin/bash
numRow=3
awk 'n[$1]<'$numRow' {a[$1]=a[$1]"\n"$0; n[$1]++} END { asort(a,b); for (x in b) print b[x] }' file
输出:
chr1 3003204 3003454 * 37 +
chr1 3003235 3003485 * 37 +
chr1 3003148 3003152 * 37 -
chr11 71863609 71863647 * 37 +
chr11 71864025 71864275 * 37 +
chr11 71864058 71864308 * 37 -
chrY 90828920 90829170 * 23 -
chrY 90829096 90829346 * 23 +
chrY 90828924 90829174 * 23 -
答案 2 :(得分:1)
如果喜欢用Python使用熊猫来做到这一点。这是我的答案:
#!/bin/env python
import sys
import pandas as pd
column = 0
number = 1
method = pd.Series.head # or pd.Series.sample
pd.read_table(sys.stdin, header=None) \
.groupby(column) \
.apply(method, n=number) \
.to_csv(sys.stdout, sep="\t", index=False, header=False)
pd.read_table
将读取表格文件。它的作用与pd.read_csv(..., sep='\t')
相同。
header=None
会告诉熊猫不要将第一行用作标题,这是默认情况。
.groupby
将按DataFrame的给定列分组。
给定关键字参数.apply(method, n=number)
,method
将在每个组上调用n=number
。
.to_csv
会将DataFrame(在这种情况下为制表符分隔)写入,而没有DataFrame的索引和标头输出到stdout。
%$ python myscript.py < ${input_tsv} > ${output_tsv}
Pandas是一个大包装,需要时间来加载。因此,该脚本比awk
脚本要慢。但是在更大的Python程序中可能很有用。
包含49144条记录的BED文件。
在Zsh中从@jkshah运行Awk脚本:
%$ awk '!($1 in a) {a[$1]=$0} END { asort(a,b); for (x in b) print b[x] }' ${bedfile} | sort >/dev/null
%$ shuf ${bedfile} | awk '!($1 in a) {a[$1]=$0} END { asort(a,b); for (x in b) print b[x] }' | sort >/dev/null
大约21毫秒的挂墙时间(平均70次运行)。 第二个大约30毫秒的挂墙时间(平均70次运行)。
使用%timeit
魔术在IPython中运行Python语句:
In [1]: %timeit pd.read_table("Every10cM.sort.bed", header=None).groupby(0).apply(pd.Series.head, n=1).to_csv(sep="\t", index=False, header=False)
In [2]: %timeit pd.read_table("Every10cM.sort.bed", header=None).groupby(0).apply(pd.Series.sample, n=1).to_csv(sep="\t", index=False, header=False)
大约两个时间为72 ms(平均70次运行)。所以它相当慢...