博客總目錄:http://www.cnblogs.com/weibaar/p/4507801.html
----
前言: 應用背景兼吐槽
繼續延續之前每個月至少一次更新博客,歸納總結學習心得好習慣。
這次的主題是論R與excel的結合,又稱 論如何正確把EXCEL文件喂給R處理
分為:
1、 xlsx包安裝及注意事項
2、用vba實現xlsx批量轉化csv
以及,這個的對象,針對跟我一樣那些從R開始接觸編程的,一直以來都是用excel做數據分析的人……編程大牛請輕拍
之所以要研究這個,是因為最近工作上接了個活,要把原來在excel端的報表遷移到R端,自動輸出可視化圖形,並制作PDF或PPT。
這個活可以分為四個階段:
1)源數據整理與搭建 & 需求分析
2)依據需求,R語言數據處理及輸出處理后數據+圖表
3)用markdown或者其他手段自動把圖表復制到報告里
4)報告使用人自己編輯整合數據。
全程要求除了數據准備不是自動化,其他都要是自動化,能省就省。。而R本身與xlsx的融合並不好。
而R讀取xlsx數據,就是我遇到的第一道檻。
這個活的數據都是人工從公司網頁端數據庫下載后儲存在xlsx里的(用sql直連數據庫的權限很難開)。嘗試過直接從數據庫端下載csv格式,但是一來格式時有錯漏,二來直接下csv格式文件大小過大(單個文件從幾兆變成幾十兆),所以最終還是決定以xlsx格式儲存,再另作打算。
相信對於那些從excel遷移到R工作的人,也會遇到同樣的問題:
一、xlsx包
首先嘗試用R包解決。即xlsx包。
xlsx包在加載時容易遇到問題。基本都是由於java環境未配置好,或者環境變量引用失敗。因此要首先配置java環境,加載rJava包。
百度了一下,網上已有很多解決方案。我主要是參考這個帖子,操作步驟為:
1、 安裝最新版本的java。如果你用的R是64位的,請下載64位java。
下載地址: http://www.java.com/en/download/manual.jsp
要安裝在 C:\Program Files\Java 下面,win8的尤其小心不要安裝為C:\Program Files(x86)。可能是R在讀取路徑時,對x86這樣的文件夾不大好識別吧,我第一次裝在x86里,讀取是失敗的。
2、在R中加載環境,即一行代碼,路徑要依據你的java版本做出更改。 R
Sys.setenv(JAVA_HOME='C:\\Program Files\\Java\\jre1.8.0_45\\')
之后再加載rjava包或者xlsx包就成功了。
xlsx包加載成功后,用read.xlsx就可以直接讀取xlsx文件,還可以指定讀取的行和段,以及第幾個表,以及可以保存為xlsx文件,這個包還是很強大的。
但是這個方法存在兩個問題:
1、不是所有的公司電腦都能自由的配置java環境。很多人的權限是受限的。而且有些公司內部應用是在java環境下配置的。就算你找了IT去安裝java,但是一些內部應用可能會因為版本號兼容問題而出錯,得小失大。
2、用xlsx包讀取數據,在數據量比較小的時候速度還是比較快的。但是如果xlsx本身比較大,包含數據多,read.xlsx效率會很低,不如data.table包的fread讀取快捷以及省內存。但fread函數不支持xlsx的讀入。。。
(參見這篇帖子,里面對千萬行數據,fread也只用了10秒左右,比常規的read.table或者read.csv至少省時一倍)
綜上,由於java環境的復雜性與兼容度,還有xlsx包本身讀取速度的限制,用xlsx包讀取xlsx包的方法,更適合於:
1、個人電腦,自己想怎么玩都無所謂,或者高大上的linux, mac環境
2、數據量不會特別大,而且excel文件很干凈,需要細節的操作
不湊巧的是,這個方法不適合我,於是只好另找辦法了。
二、用VBA把xlsx批量轉化為csv格式
在上面的嘗試已經發現,xlsx本身就是這個復雜問題的最根本原因。與之相反,R對csv等文本格式支持的很好,而且有fread這個神器,要處理一定量級的數據,還是得把xlsx轉化為csv格式。
以此為思路,在參考了兩個資料后,我成功改寫了一段VBA,可以選中需要的xlsx,然后在其目錄下新建csv文件夾,把xlsx批量轉化為csv格式。
代碼如下:
1 Sub getCSV() 2 '這是網上看到的xlsx批量轉化,而改寫的一個xlsx批量轉化csv格式
3 '1)批量轉化csv參考:http://club.excelhome.net/thread-1036776-2-1.html
4 '2)創建文件夾參考:http://jingyan.baidu.com/article/f54ae2fcdc79bc1e92b8491f.html
5 '這里設置屏幕不動,警告忽略
6 Application.DisplayAlerts = False
7 Application.ScreenUpdating = False
8 Dim data As Workbook 9 '這里用GetOpenFilename彈出一個多選窗口,選中我們要轉化成csv的xlsx文件,
10 file = Application.GetOpenFilename(MultiSelect:=True) 11 '用LBound和UBound
12 For i = LBound(file) To UBound(file) 13 Workbooks.Open Filename:=file(i) 14 Set data = ActiveWorkbook 15 Path = data.Path 16 '這里設置要保存在目錄下面的csv文件夾里,之后可以自己調
17 '參考了里面的第一種方法
18 On Error Resume Next
19 VBA.MkDir (Path & "\csv") 20 With data 21 .SaveAs Path & "\csv\" & Replace(data.Name, ".xlsx", ".csv"), xlCSV 22 .Close True
23 End With
24 Next i 25 '彈出對話框表示轉化已完成,這時去相應地方的csv里查看即可
26 MsgBox "已轉換了" & (i-1) & "個文檔"
27 Application.ScreenUpdating = True
28 Application.DisplayAlerts = True
29 End Sub
操作很簡單:
把代碼復制進excel的vba編輯器里,然后運行getcsv這個宏,會跳出一個窗口,要求選擇你要轉化的xlsx文件。(可多選)
選中以后,等一段時間,再回到xlsx文件下,會多一個csv文件夾,里面就是我們要導入R的文本文件了。
這個方法的好處是:
1、操作簡單,直接依托於excel的VBA操作,不用配置java環境,之后溝通成本/換電腦成本小
2、特別適用於有一定數據量,但是數據格式整齊的文件,譬如從某數據端讀入的數據。用fread還可以控制讀取的行(skip=NNN),代碼寫入整潔方便。就算有一些異行數據,也可以事先用VBA進行操作,簡單方便。
綜上,我最后用的是第二種方法。
不過第一種方法,如果有java環境還是盡量配置比較好。因為有些有名的包都要依托於這個java環境。最典型的就是Rwordseg包(中文分詞)
補充資料:
話說,當我最開始接觸這個任務的時候,我真的沒想到最后我是用VBA解決的問題。也有很多人會用python解決類似問題吧,可惜我現在暫時還抽不出空來學python。
不過黑貓白貓抓到老鼠就是好貓……繼學會R以后,我又被迫學會了改VBA代碼,心塞塞
關於VBA,有一些參考資料如:
1) VBA對文件夾的操作:
Excel VBA - 遍歷某個文件夾中文件、文件夾及批量建立txt
這篇博文里介紹了很多用VBA實現建文件夾、改名等的應用。雖然個人覺得用R做dir()或者list.files更加直觀一些,不過可以參考。
如何在Excel中用VBA創建文件夾?
兩種創建文件夾的方法,我直接用了第一種。。。
2)VBA合並工作表,生成目錄:
excelhome介紹的教程
#一宏微教程#第008~010期——Excel文件里工作表太多怎么辦?
另外在文件夾層面,用R進行文件操作,可查看以下教程:
用R進行文件系統管理