看板 Linux 關於我們 聯絡資訊
※ 引述《egoweaver (Hiko)》之銘言: : 啊,打完發現我不是在隔壁版。補個 Linux 點。用 awk 的話其實也滿快的: : # 計算 A_1 與 A_2 相同的列數 (若它們分別為第一第二欄) : awk '$1 == $2 {i++}END{print i}' [your raw data] : # 計算 A_1 與 A_2 都同樣是 ./. 的列數 : awk '$1 == "./." && $2 == "./." {i++}END{print i}' [your raw data] : # 計算 A_1 與 A_2 不相同的列數 : awk '$1 != $2 {i++}END{print i}' [your raw data] : # 計算每列中有幾個 "./." : awk '{for(i = 1; i <= NF; i++) {if($i == "./.") n++}; \ : print n >> "number.txt";}' [your raw data] : # 如果要把 "./." 的個數當作一欄併回原檔案 : paste [your raw data] number.txt >> newfile.txt : ※ 引述《k97231 (AL)》之銘言: : : 基本上的資料格式長這樣 : : ID A_1 A_2 B_1 B_2 …… : : 1 0/0 0/0 : : …… : : 依據相同字母的樣本(像是A_1和A_2) : : 逐列統計四種欄位的數量 : : 1. A_1和A_2相同 : : 2. A_1和A_2都一樣是./. : : 3. A_1和A_2不一樣 : : 4. 以及任一樣本含有./.的欄位數量 這類型的統計用 awk 還真的滿簡單的. 不過麻煩的是在這一句 「依據相同字母的樣本(像是A_1和A_2)」 也就是 A_1 跟 A_2 統計, B_1 跟 B_2 統計, 是吧? 如果需要統計的欄位很多 (ex: A_1...Z_1), 那就比較煩一點.. 考慮單一個資料來說. 無腦的把條件直接寫下來 SCREEN:working rickie$ cat stats.awk BEGIN{ cnt_match=0; cnt_dot_match=0; cnt_dot=0; cnt_not_match=0; } (NR > 1){ if ( $2 == $3 ) {cnt_match++;} if ( $2 == $3 && $2 == "./." ) {cnt_dot_match++;} if ( $2 == "./." || $3 == "./." ){cnt_dot++;} if ( $2 != $3 ) {cnt_not_match++;} } END{ printf(" A_1 = A_2 : %d\n",cnt_match); printf(" A_1 = A_2 = ./. : %d\n",cnt_dot_match); printf("A_1 or A_2 = ./. : %d\n",cnt_dot); printf(" A_1 != A_2 : %d\n",cnt_not_match); } 從你的 raw data 複製了一份 600 萬筆資料的檔案 SCREEN:working rickie$ wc -l temp2.dat 6000001 temp2.dat 試跑一下 SCREEN:working rickie$ time awk -f stats.awk temp2.dat A_1 = A_2 : 3000000 A_1 = A_2 = ./. : 1000000 A_1 or A_2 = ./. : 2000000 A_1 != A_2 : 3000000 real 0m10.119s user 0m9.940s sys 0m0.065s 稍微優化一下 SCREEN:working rickie$ cat stats2.awk BEGIN{ cnt_match=0; cnt_dot_match=0; cnt_dot=0; cnt_not_match=0; } (NR > 1){ if ( $2 == $3 ) { cnt_match++; if ($2 == "./." ) { cnt_dot_match++; cnt_dot++; } } else { cnt_not_match++; if ( $2 == "./." || $3 == "./." ){cnt_dot++;} } } END{ printf(" A_1 = A_2 : %d\n",cnt_match); printf(" A_1 = A_2 = ./. : %d\n",cnt_dot_match); printf("A_1 or A_2 = ./. : %d\n",cnt_dot); printf(" A_1 != A_2 : %d\n",cnt_not_match); } 再跑一次 SCREEN:working rickie$ time awk -f stats2.awk temp2.dat A_1 = A_2 : 3000000 A_1 = A_2 = ./. : 1000000 A_1 or A_2 = ./. : 2000000 A_1 != A_2 : 3000000 real 0m4.999s user 0m4.937s sys 0m0.044s 如果可以不要檔頭, 那 (NR > 1) 這個判斷拿掉, 可以再少一點點時間 SCREEN:working rickie$ time awk -f stats3.awk temp3.dat A_1 = A_2 : 3000000 A_1 = A_2 = ./. : 1000000 A_1 or A_2 = ./. : 2000000 A_1 != A_2 : 3000000 real 0m4.805s user 0m4.749s sys 0m0.039s 大概是醬~ 還有 awk 變數其實不用預先宣告, BEGIN 裡其實可以省略 單純只是個人強迫症發作... -- 文章代碼(AID): #1H6m-prS (Gossiping) [ptt.cc] [問卦] 有沒有雪藏的八卦?
liusim:我覺得應該還是念雪藏 你們不覺得念雪藏怪怪的嗎?02/13 12:03
ispy03532003:原來如此 要唸"藏"阿 之前都一直講"藏"02/13 12:04
koster:我真的不知道要念雪藏 一直都以為念雪藏是對的 長知識了02/13 12:06
pkmu8426:其實藏和藏都是錯的 只有藏才是對的02/13 12:11
Eternity424:幹你娘 你們都打藏誰知道講哪個音02/13 12:16
-- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 220.133.28.48 ※ 文章網址: https://www.ptt.cc/bbs/Linux/M.1530243076.A.2E6.html ※ 編輯: rickieyang (220.133.28.48), 06/29/2018 11:35:49
k97231: 這個好像執行上似乎會更快一點 來研究一下 awk 感謝 07/02 22:58