跳到主要內容

第一次的 StackOverflow

今天為一個用 R 畫畫的小腳本第一次到傳說中的萬事屋 StackOverflow 去發問了,謹為文記念。

在我一拐一拐學著 R 的過程中,帶我前進的拉力的成分幾乎全是 StackOverflow (至於推力嘛,當然就是在實驗室生活中越養越肥美的懶病),如果沒有它,我想寫出來偷懶的腳本十個有十一個會寫到 library(stringr) 就結束囉。

今天的問題來自之前為了把電位測定的紀錄畫成圖而寫的腳本,是個裡面充滿巢狀的 for - loop 迴圈的恐怖玩意,它雖然會動但因為難以讀懂所以也不太可能再加功能進去。無奈我發下豪語說「啊,這個反正用 R 弄很快」的那個心血來潮只生出個別樣本的電位圖,至於總結的摘要圖當時就沒做了。

不過說到底,最重要的根本就是總結圖……

動手改的過程當中對於執行速度之緩慢感到不耐煩,想起之前看過的讀取速度比較文,我決定歸咎給最開始的 read.table() 跑太慢,目前讀一個原始檔大概要花十秒。

開開心心的戴入 data.table 套件,我理想的流程是這樣的:把讀取的部分用 fread() 重寫一次,然後進到後面的迴圈海整理出可讀的版本再往下做。事實上……

Error in fread("test.txt", fill = TRUE, sep = "\t", quote = "", header = FALSE) : 
Expecting 3 cols, but line 258088 contains text after processing all cols. Try again with fill=TRUE. Another reason could be that fread's logic in distinguishing one or more fields having embedded sep='  ' and/or (unescaped) '\n' characters within unbalanced unescaped quotes has failed. If quote='' doesn't help, please file an issue to figure out if the logic could be improved.

好吧(´・ω・`)

我進到原始檔,發現第 258088 列在實驗時做了註記,顯然 fread() 讀取到這裡發現多了一行感到無法接受了。

可是一般來說這個問題應該要被 fill = TRUE (如果每列行數不同的話則填入 NA )解決才對呀?fread() 的說明上寫說它會自動偵測前幾列的格式來決定讀取的方式,所以我進一步試試讓它從錯誤的附近開始讀。

fread("test.txt", fill = TRUE, header = FALSE, sep = "\t", skip = 250000)

一樣的錯誤訊息(´・ω・`)

fread("test.txt", fill = TRUE, header = FALSE, sep = "\t", skip = 258080)

問題就解決了……嗯不對,其實沒有,大半的檔案根本都被放棄掉了。

於是我就上了 StackOverflow,這邊網友回文的速度真的是有夠快,難怪能夠累積出我不管碰到什麼怪異問題都能在這找出答案的資訊量。

得到的答案包括:

何不用 read.table()
在標頭的地方強行新開一行讓註解有地方放就不會跳錯誤囉
先強行把原檔沒註解的部分都填個 tab 上去讓 R 知道要多分一行出來
你可以先不分列讀(用 readLines()),然後再用 tstrsplit() 之類的方法把它拆開

雖然先把原檔的格式修正是概念上最正確的作法,無奈儀器吐出來的格式就是這樣子,而另外修正它會比用 read.table() 讀花上更多時間,所以大部分的回答最後都以長知識的效果為主。

最後一個想法倒是勾起我的興趣,如果使用 fread() 先讀再切會不會還是比較快呢?

microbenchmark(
tstrsplit(unlist(fread("test.txt", sep = "\n", data.table = F)), "\t", type.convert = T, names = T, keep = 1:4),
read.table("test.txt", header = F, sep = "\t", fill = T),
times = 1)

結果手動拆開就比直接用 read.table() 讀慢了:

Unit: seconds
expr
 tstrsplit(unlist(fread("test.txt", sep = "\\n", data.table = F)),      "\\t", type.convert = T, names = T, keep = 1:4)
                                                              read.table("test.txt", header = F, sep = "\\t", fill = T)
      min       lq     mean   median       uq      max neval
 2.185109 2.185109 2.185109 2.185109 2.185109 2.185109     1
 1.611715 1.611715 1.611715 1.611715 1.611715 1.611715     1

哎呀哎呀。

留言

這個網誌中的熱門文章

尿管水球考

Photo credit: Crystal Explosion via photopin (license)   那約莫是intern到一半的時候。記得那天我放尿管就要大功告成,隨手拿起換藥車上的空針想把固定用的水球打起來結束這回合的時候,碰巧路過的護理師一個飛身順手抄起空針: 「且住!你這針筒裡面裝的是……生理食鹽水吧!」   我定睛一看,啊呀,落在換藥車桌面上的空罐子果然是生理食鹽水,顯然是在抽的時候沒有專心。 「多謝女俠提醒,不過……那可以幫我抽一管純水嗎?我得扶著尿管,不太方便。」

文獻管理軟體:關於ReadCube, Mendeley, Papers有時還有其他

出發點 我家的文獻通常是這樣來的: 我有訂閱 Science 的 編輯精選 跟幾個與我題目有關的 關鍵字 實驗室平均來說每週會有一篇書報討論 臉書牆上看似有趣的玩意 它們會先成為瀏覽器上關不掉的分頁,過一段時間或是瀏覽器當掉幾次之後,心不甘情不願的搬家到下載項目,然後很多時候就長住在那兒,直到碰到比較無聊的演講開始整理時才會發現有些東西其實下載了五遍。 使用習慣 會在不同的裝置和系統上面閱讀 尋找一篇文的關鍵字通常是作者、期刊、跟內容的隨機組合 提到依稀記得的文章卻想不起來時會覺得很焦慮 從這幾點出發,對我來說特別重要的特質是 跨平台同步 、 全文檢索 (最好聰明點)、還有 執行速度快 。 除了這些之外,當然隨寫隨引的引用工具好不好用還有推薦文獻如何也有影響,不過就我來說為了配合協作,引用工具還是配合實驗室,反正也不是那麼頻繁的用上;至於推薦嘛,雖然廣泛閱讀是很重要啦,不過即使沒有推薦功能文獻資料夾裡也都充滿了不認識的孩子,我想推薦功能大半還是滿足屯書癖而已。 Endnote 老牌的文獻管理,作為和 Word 搭配的引用工具來說,除了厚重了點還有搭配追蹤修訂功能有點容易當機之外沒什麼大問題,最近的版本似乎也推出了跨平台同步的功能。其實它也能從 PDF 解析引用資料或是用引用資料尋找全文,不過 PDF 閱讀器相當陽春,我目前只有在寫東西時才會打開它,並不在上面閱讀。 ReadCube Nature Publishing Group 和 Wiley 推廣得相當認真的閱讀器,界面上也算漂亮。在文章管理上使用看起來像資料夾但實質上是標籤的處理方式。它雖然有跨平台同步功能,但只有付費用戶才能使用。 我一開始對於它的擴展 PDF 1 功能很感興趣,但使用起來其實還好,因為我的領域裡有不少論文本來就會用超連結放引用,但它的閱讀器本身卻不支援 PDF 原來就有的超連結,所以常常發生這篇論文沒辦法擴展,但原來的超連結又不能用,只好複製下來 Google 去也。擴展變成一個偶爾方便一些,但大多時候添麻煩的雞肋存在。 除了不支援超連結,它的 PDF 閱讀器在我的機器上 2 字體的渲染也有問題,比起 Acrobat自家的程式,字硬是模糊了不少,快速瀏覽的時候也常發生往後翻去的那頁空白了兩三秒才出現的狀態。另

ImageJ (1.51f) 在Mac OS 10.12 (Sierra)中會因為權限管理而無法使用Plugin

問題描述: 在將下載後的ImageJ資料夾搬到應用程式資料夾中後,程式可以使用但Plugin功能表下的項目消失。 系統資訊: OS Version: Mac OS 10.12 ImageJ: 1.51f  JAVA Version: 1.6.0_65 according to About ImageJ 1.8.0_111-b14 according to Control Panel Memory Assigned: 2854k of 7000MB (<1 li=""> No error message 原因: Mac OS 10.12為了解決使用者權限管理的漏洞,在執行應用程式時會建立一個隨機路徑的唯讀資料夾並把.app複製過去在其中執行(Gatekeeper Path Randomization)。這個作法會讓某些需要呼叫其他檔案的程式無法正常作用。   在ImageJ上,如果在Image>Show Info功能表(或Command + I)中的「ImageJ Home:」後面的路徑的開頭是"/private",那就可能是Gatekeeper Path Randomization在作怪。   將執行檔從應用程式資料夾中複製到桌面(Option+拖曳)後刪掉原檔再把執行檔複製回去可以修正這個權限問題。 參考資料: Sierra and Gatekeeper Path Randomization Kind and timely support from Wayne Rasband (NIH/NIMH)