Project-Management

編輯逗號分隔值 (CSV) 文件的策略

  • December 8, 2010

當我從事數據分析項目時,我經常將數據存儲在逗號或製表符分隔(CSV、TSV)數據文件中。而數據通常屬於專用的數據庫管理系統。對於我的許多應用程序,這將是過度的事情。

我可以在 Excel(或者可能是另一個電子表格程序)中編輯 CSV 和 TSV 文件。這有以下好處:

  • 電子表格使輸入數據變得容易

還有幾個問題:

  • 使用 CSV 和 TSV 文件會導致各種警告消息,包括各種功能丟失以及如何僅保存活動工作表等。因此,如果您只想打開文件並進行一些更改,那就很煩人了。
  • 它進行了許多“所謂的智能”轉換。例如,如果你輸入 12/3,它會認為你要輸入一個日期。 **更新:**我應該提到日期示例只是眾多示例之一;大多數問題似乎與不適當的轉換有關。特別是,看起來像數字或日期的文本字段會導致問題。

或者,我可以直接在標准文本編輯器中處理文本文件。這樣可以確保我輸入的是記錄的內容。然而,這是一種非常尷尬的數據輸入方式(列不對齊;很難將數據簡單地輸入到多個單元格中;等等)。

問題

  • 處理 CSV 或 TSV 數據文件的好策略是什麼?即,什麼策略使輸入和操作數據變得容易,同時確保您輸入的內容實際上被正確解釋?
  1. 如果您對 R 感到滿意,您可以創建基本的 data.frame,然後在其上使用 fix() 函數來輸入數據。與 #5 一樣,一旦設置了 data.frame,您就可以使用一系列 readLines(n=1) (或其他)來獲取數據、驗證數據,並提供添加下一個的機會排。然後將修復留給 fix()。請參閱下面使用 scan() 實現的示例。
  2. excel 中的另一個選項會很混亂,但您可以輸入 12/9,然後讓另一列評估 =IFERROR(MONTH(DateEntryCell)/DAY(DataEntryCell),DataEntryCell)。但是,您必須維護 excel 表和 csv 表,並且在編寫 csv 時所有的抱怨都會持續存在。
  3. 或者,只要您的字段相對較短並且具有一致的長度,常規文本編輯器應該可以很好地為您提供 TSV。完成後,您始終可以將其加載到 Excel 中,並確保每行的列數符合您的預期。
  4. Emacs 可以在許多平台上使用,並且可能有一些專門用於此的東西,例如http://www.emacswiki.org/emacs/CsvMode
  5. 如果你是一個熱心的人,用編程語言快速編寫一些東西來進行數據輸入是微不足道的,數據編輯會困難得多。
  6. 一個快速的谷歌搜索顯示軟件就是為了這個目的,但似乎沒有免費軟件有什麼好處。
  7. 這聽起來很瘋狂,但超級用戶的某個人建議在訪問中編輯表格,然後將它們導出為 CSV……這簡直太瘋狂了。
  8. 當您保存為 .csv 時,它並不會阻止 excel 抱怨,但是您可以在數據輸入字段之前鍵入一個撇號,這使得它在自動格式化方面保持獨立。很好,這(至少在 Office 2007 中)不會在 csv 文件中留下撇號。

更新: 我一直在討論這個問題,因為我也有這個問題。到目前為止,我見過的最好/最簡單的數據輸入解決方案是KillinkCSV。它不是“免費”軟件,它是具有 30 天試用期和合理價格(約 27 美元)的共享軟件。不過,我不確定我在編輯現有 CSV 時有多信任它 - 我給了它一個非常大(並且可能格式正確)的 CSV,但它無法讀取所有行。然而,對於一個相當大(20 MB)的文件來說,它似乎工作得很好,而且較大文件的問題可能是我的用戶錯誤。

示例:

#This function takes a what argument like in scan, 
#a list with the types to be used, see usage example 
#at the end of this code block
#dataEntry will keep reading in values until 
#the values it reads in matches what is in 
#"terminateon".
#limitations: Many
dataEntry <- function(what,terminateon)
{
 CONTINUE <- TRUE #Make sure we start the loop
 data <- NULL #Create empty data so that the data.frame can define itself
 ti <- NULL
 while(CONTINUE)
 {
   ti <- NULL    
   ti <- tryCatch(
     {as.data.frame(scan(what=what, nlines=1, multi.line=FALSE, comment.char="",quiet=TRUE))},
     error=function (e) {print("Error in data entry! Line not stored.")
                         return(NULL)},
     warning=function(w) {print("Error in data entry! Line not stored.")
                          return(NULL)},
     finally={ti <- NULL}
   ) #Try getting the data according to the parameters in 'what' one row at a time.
   if (!is.null(ti))
   {
     if ((ncol(ti)==length(what)) & (nrow(ti)==1)) {
       data <- rbind(data,ti) #If there wasn't an error, add ti to the previous value  
     } else {
       print("Too many or not enough values on previous entry.")
       print("Tail of current data:")
       print(tail(data))
     }
   }
   if (!is.null(ti) & all(ti == terminateon)) 
   {
     CONTINUE <- FALSE
     data <- data[-c(nrow(data)),]
   } #if we've recieved the final value we won't continue and the last row is invalid so we remove it
 }
 return(data)
}

dataEntry(list(x=integer(), y=numeric(), z=character()),terminateon=c(999,999,"Z"))

引用自:https://stats.stackexchange.com/questions/5238

comments powered by Disqus

相關問答