Bash

使用 awk 從 CSV 文件中僅選擇一個欄位小於門檻值的行

  • June 2, 2021

處理包含許多(10000+)行的多列csv文件的後處理:

ID(Prot), ID(lig), ID(cluster), dG(rescored), dG(before), POP(before)
9000, lig662, 1, 0.421573, -7.8400, 153
10V2, lig807, 1, 0.42692, -8.0300, 149
3000, lig158, 1, 0.427342, -8.1900, 147
3001, lig158, 1, 0.427342, -8.1900, 147
10V2, lig342, 1, 0.432943, -9.4200, 137
10V1, lig807, 1, 0.434338, -8.0300, 147
4000, lig236, 1, 0.440377, -7.3200, 156
10V1, lig342, 1, 0.441205, -9.4200, 135
4000, lig497, 1, 0.442088, -7.7900, 148
9000, lig28, 1, 0.442239, -7.5200, 152
3001, lig296, 1, 0.444512, -7.8900, 146
10V2, lig166, 1, 0.447681, -7.1500, 157
....
4000, lig612, 1, 0.452904, -7.0200, 158
9000, lig123, 1, 0.461601, -6.8000, 160
10V1, lig166, 1, 0.463963, -7.1500, 152
10V1, lig369, 1, 0.465029, -7.3600, 148

到目前為止我做了什麼

我正在使用以下awk程式碼集成到一個bash函式中,該函式從 CSV 中提取 1%(頂行)並將其保存為新的 CSV(包含因此減少的行數):

take_top44 () {
   # Take the top lines from the initial CSV
   awk -v lines="$(wc -l < original.csv)" '
   BEGIN{
     top=int(lines/100)
   }
   FNR>(top){exit}
   1
   ' original.csv >> csv_with_top_lines.csv
}

我現在想做什麼

如何修改我的awk程式碼以在原始 CSV 上應用更具選擇性的過濾器?例如,根據第 4 列(in)的值(浮點數)過濾數據dG(rescored)

例如,我需要使用最低值(始終在第二行,minForth = 0.421573)作為參考,並列印 CSV 中$4小於所選門檻值的所有行(例如,高於 20% minForth):

$4<=(1+0.2)*min))'

如果您只想過濾第 4 個欄位低於門檻值的所有行,則以下awk命令將起作用:

awk -F',' -v margin=0.2 'FNR==2 {min=$4} FNR>1&&($4<=(1+margin)*min)' input.csv

或者,如果您也想在過濾後的輸出中包含標題:

awk -F',' -v margin=0.2 'FNR==2 {min=$4} FNR==1||($4<=(1+margin)*min)' input.csv

這會將歸檔分隔符設置為,(但請注意,您的文件是非標準 CSV,因為您有額外的空格分隔欄位)並將margin值為 的變數0.2導入awk程序。

在程序內部,如果我們在第 2 行 ( ) ,它會將變數min值設置為第 4 列中的值。FNR==2如果我們在第 1 行(標題 - 如果你想要的話)或者我們在文件的數據部分並且第 4 個欄位小於1+margin最小值的倍數,它只會列印目前行。

引用自:https://unix.stackexchange.com/questions/652201