Csv AWK:基于所选列的多步骤数据过滤

Csv AWK:基于所选列的多步骤数据过滤,csv,awk,Csv,Awk,我正在处理以固定格式排列的多列CSV的后处理:第一列对应行号(ID),第二列包含其总体(POP,落入该ID的样本数),第三列(dG)表示该ID的一些固有值(始终为负值): 为了减少行数,我过滤了此CSV,目的是使用以下AWK表达式搜索第二列(POP)中编号最高的行: # search CSV for the line with the highest POP and save all linnes before it, while keeping minimal number of the li

我正在处理以固定格式排列的多列CSV的后处理:第一列对应行号(ID),第二列包含其总体(POP,落入该ID的样本数),第三列(dG)表示该ID的一些固有值(始终为负值):

为了减少行数,我过滤了此CSV,目的是使用以下AWK表达式搜索第二列(POP)中编号最高的行:

# search CSV for the line with the highest POP and save all linnes before it, while keeping minimal number of the linnes (3) in the case if this line is found at the begining of CSV.
awk -v min_lines=3 -F ", " 'a < $2 {for(idx=0; idx < i; idx++) {print arr[idx]} print $0; a=int($2); i=0; printed=NR} a > $2 && NR > 1 {arr[i]=$0; i++}END{if(printed <= min_lines) {for(idx = 0; idx <= min_lines - printed; idx++){print arr[idx]}}}' input.csv > output.csv
为了将输出CSV中的行总数减少到3-5行,在将每行与pop列中具有最大值的行进行比较时,如何自定义我的过滤器,以便仅保存差异较小的行(例如,pop列中的值应匹配(pop>0.5 max(pop))?最后,我需要始终保持第一行以及输出中具有最大值的行。因此,AWK解决方案应按以下方式过滤多字符串CSV(请忽略#中的内容):


这两个阶段
awk
应该适合您:

awk-F','-vn=2'NR==1{next}
FNR==NR{if(max<$2){max=$2;if(FNR==n)n++}next}
FNR(.5*max)文件
ID,POP,dG
1, 7, -9.6000
9, 16, -7.8100
26, 20, -6.6500

但是为什么
6,10,-8.0100
不在输入中,因为
10
正好是
20
的50%?这个问题似乎不一致或缺乏细节。您希望结果精确到3-5行吗?与POP保持记录≤ 最大0.5(POP)不会导致您发布的输出,因为它只会删除第9条记录。感谢您的更正!事实上,我的意思是,我需要在输出中保留pop D接近pop MAX(pop>0.5 MAX(pop))的行,因此它不适合pop=10的行,而是明确地采用第9行(pop=16),如预期输出中所示。请将您的示例简化为a。任何带有滚动条的示例输入/输出都不是最小的,因此浪费我们的时间试图理解所有内容。你可以用10行而不是70行的输入来演示你需要帮助的任何问题。效果很好!但是有一个错误,当POP max的行是第一行时(总是应该在输出中采用,而不考虑值),它会采用POP远低于50%的一些行,请检查更新答案。是的,这是有效的!抱歉,更精确一点-如果在第一行中找到pop(max),是否可以保留输出中的前两行,而不是像现在一样保留第一行?:-)很抱歉,这就是为什么不鼓励在评论中添加需求的原因。请用示例输入和预期输出更新问题,然后我可以相应地修改答案。没有问题,实际上当前版本也很酷,所以我接受它!再次感谢你。干杯
# search CSV for the line with the highest POP and save all linnes before it, while keeping minimal number of the linnes (3) in the case if this line is found at the begining of CSV.
awk -v min_lines=3 -F ", " 'a < $2 {for(idx=0; idx < i; idx++) {print arr[idx]} print $0; a=int($2); i=0; printed=NR} a > $2 && NR > 1 {arr[i]=$0; i++}END{if(printed <= min_lines) {for(idx = 0; idx <= min_lines - printed; idx++){print arr[idx]}}}' input.csv > output.csv
ID, POP, dG
1, 7, -9.6000
2, 3, -8.7700
3, 6, -8.6200
4, 4, -8.2700
5, 6, -8.0800
6, 10, -8.0100
7, 9, -7.9700
8, 8, -7.8400
9, 16, -7.8100
10, 2, -7.7000
11, 1, -7.5600
12, 2, -7.5200
13, 9, -7.5100
14, 1, -7.5000
15, 2, -7.4200
16, 1, -7.3300
17, 1, -7.1700
18, 4, -7.1300
19, 3, -6.9200
20, 1, -6.9200
21, 2, -6.9100
22, 2, -6.8500
23, 10, -6.6900
24, 2, -6.6800
25, 1, -6.6600
26, 20, -6.6500
ID, POP, dG 
1, 7, -9.6000    
9, 16, -7.8100
26, 20, -6.6500 # this is POP max detected over all lines