數(shù)據(jù)導(dǎo)入利器——rio包

筆記說(shuō)明

在讀《Modern R with the tidyverse》一書時(shí)發(fā)現(xiàn)了這個(gè)非常好用的R包,做此筆記記錄。本筆記記錄rio包的數(shù)據(jù)導(dǎo)入功能。導(dǎo)出功能說(shuō)明見(jiàn):用rio包進(jìn)行數(shù)據(jù)導(dǎo)出

數(shù)據(jù)導(dǎo)入

Hadley Wickham在《R for Data Science》中總結(jié)的探索性數(shù)據(jù)分析的分析流程

數(shù)據(jù)導(dǎo)入是數(shù)據(jù)分析的第一步。實(shí)際工作中數(shù)據(jù)的來(lái)源和原始數(shù)據(jù)文件的格式多種多樣。對(duì)應(yīng)不同的原始文件來(lái)源或格式就有很多不同的讀取數(shù)據(jù)的R包。學(xué)習(xí)、使用起來(lái)非常麻煩。在rio包之前,為了滿足數(shù)據(jù)導(dǎo)入需要,大概需要學(xué)習(xí)的R包和其對(duì)應(yīng)的數(shù)據(jù)文件類型如下:

  • readr包 - text files(如csv, tsv, fwf文件)
  • haven包 - SPSS, Stata, and SAS files
  • readxl包 - excel files
  • DBI包 - databases
  • jsonlite包 - json
  • xml2包 - XML
  • httr包 - Web APIs
  • rvest包 - HTML (Web Scraping)

rio包及其數(shù)據(jù)導(dǎo)入功能

rio包封裝了很多數(shù)據(jù)導(dǎo)入和導(dǎo)出的包,并將不同包的數(shù)據(jù)導(dǎo)入導(dǎo)出操作統(tǒng)一到兩個(gè)函數(shù)上:import()export(),通過(guò)文件的后綴名來(lái)判斷文件類型。這使得在R中進(jìn)行數(shù)據(jù)的導(dǎo)入導(dǎo)出操作變得非常簡(jiǎn)單。有關(guān)rio包的更多信息可以參見(jiàn):https://cran.r-project.org/web/packages/rio/vignettes/rio.html
下面對(duì)rio包的一些數(shù)據(jù)導(dǎo)入功能進(jìn)行展示(基本參照《Modern R with the tidyverse》中對(duì)應(yīng)的內(nèi)容,所使用的數(shù)據(jù)可以在https://github.com/b-rodrigues/modern_R/tree/master/datasets下載):

  • 加載rio包
library(rio)
## The following rio suggested packages are not installed: ‘csvy’, ‘feather’, ‘fst’, ‘hexView’, ‘readODS’, ‘rmatio’, ‘xml2’
## Use 'install_formats()' to install them
  • 使用import()進(jìn)行數(shù)據(jù)導(dǎo)入
#導(dǎo)入csv文件
mtcars <- import("data/mtcars.csv")
head(mtcars)
##   mpg cyl disp  hp drat    wt  qsec vs am gear carb
## 1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## 2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## 3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## 4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## 5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## 6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

在Windows系統(tǒng)下,對(duì)于萌新來(lái)說(shuō)需要注意的一點(diǎn)是不能直接把文件路徑粘貼過(guò)來(lái),windows系統(tǒng)使用“\”標(biāo)識(shí)路徑,而R使用“/”表示路徑。
導(dǎo)入其他格式的數(shù)據(jù)也是一樣:

#導(dǎo)入stata數(shù)據(jù)
mtcars_stata <- import("data/mtcars.dta")
#導(dǎo)入sas數(shù)據(jù)
mtcars_sas <- import("data/mtcars.sas7bdat")
  • import_list()導(dǎo)入一個(gè)excel文件中的多個(gè)sheet
multi <- import_list("data/multi.xlsx")
str(multi)
## List of 2
##  $ mtcars:'data.frame':  32 obs. of  11 variables:
##   ..$ mpg : num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##   ..$ cyl : num [1:32] 6 6 4 6 8 6 8 4 4 6 ...
##   ..$ disp: num [1:32] 160 160 108 258 360 ...
##   ..$ hp  : num [1:32] 110 110 93 110 175 105 245 62 95 123 ...
##   ..$ drat: num [1:32] 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
##   ..$ wt  : num [1:32] 2.62 2.88 2.32 3.21 3.44 ...
##   ..$ qsec: num [1:32] 16.5 17 18.6 19.4 17 ...
##   ..$ vs  : num [1:32] 0 0 1 1 0 1 0 1 1 1 ...
##   ..$ am  : num [1:32] 1 1 1 0 0 0 0 0 0 0 ...
##   ..$ gear: num [1:32] 4 4 4 3 3 3 3 4 4 4 ...
##   ..$ carb: num [1:32] 4 4 1 1 2 1 4 2 2 4 ...
##  $ iris  :'data.frame':  150 obs. of  5 variables:
##   ..$ Sepal.Length: num [1:150] 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##   ..$ Sepal.Width : num [1:150] 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##   ..$ Petal.Length: num [1:150] 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##   ..$ Petal.Width : num [1:150] 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##   ..$ Species     : chr [1:150] "setosa" "setosa" "setosa" "setosa" ...

str(multi)的結(jié)果可以看出,導(dǎo)入后生成的multi對(duì)象是一個(gè)由兩個(gè)dataframe組成的list。

  • 一次性導(dǎo)入同一目錄下的所有數(shù)據(jù)文件

首先生成一個(gè)包含所有數(shù)據(jù)文件的向量:

paths <- Sys.glob("data/unemployment/*.csv")
paths
## [1] "data/unemployment/unemp_2013.csv" "data/unemployment/unemp_2014.csv"
## [3] "data/unemployment/unemp_2015.csv" "data/unemployment/unemp_2016.csv"

Sys.glob()利用正則表達(dá)式找到所有數(shù)據(jù)文件,本例中找到所有data/unemployment/目錄下以csv為后綴的文件。
之后利用import_list()一次性導(dǎo)入所有數(shù)據(jù)文件:

all_data <- import_list(paths)  
str(all_data)
## List of 4
##  $ unemp_2013:'data.frame':  118 obs. of  8 variables:
##   ..$ Commune                   : chr [1:118] "Grand-Duche de Luxembourg" "Canton Capellen" "Dippach" "Garnich" ...
##   ..$ Total employed population : int [1:118] 223407 17802 1703 844 1431 4094 2146 971 1218 3002 ...
##   ..$ of which: Wage-earners    : int [1:118] 203535 15993 1535 750 1315 3800 1874 858 1029 2664 ...
##   ..$ of which: Non-wage-earners: int [1:118] 19872 1809 168 94 116 294 272 113 189 338 ...
##   ..$ Unemployed                : int [1:118] 19287 1071 114 25 74 261 98 45 66 207 ...
##   ..$ Active population         : int [1:118] 242694 18873 1817 869 1505 4355 2244 1016 1284 3209 ...
##   ..$ Unemployment rate (in %)  : num [1:118] 7.95 5.67 6.27 2.88 4.92 ...
##   ..$ Year                      : int [1:118] 2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ unemp_2014:'data.frame':  118 obs. of  8 variables:
##   ..$ Commune                   : chr [1:118] "Grand-Duche de Luxembourg" "Canton Capellen" "Dippach" "Garnich" ...
##   ..$ Total employed population : int [1:118] 228423 18166 1767 845 1505 4129 2172 1007 1268 3124 ...
##   ..$ of which: Wage-earners    : int [1:118] 208238 16366 1606 757 1390 3840 1897 887 1082 2782 ...
##   ..$ of which: Non-wage-earners: int [1:118] 20185 1800 161 88 115 289 275 120 186 342 ...
##   ..$ Unemployed                : int [1:118] 19362 1066 122 19 66 287 91 38 61 202 ...
##   ..$ Active population         : int [1:118] 247785 19232 1889 864 1571 4416 2263 1045 1329 3326 ...
##   ..$ Unemployment rate (in %)  : num [1:118] 7.81 5.54 6.46 2.2 4.2 ...
##   ..$ Year                      : int [1:118] 2014 2014 2014 2014 2014 2014 2014 2014 2014 2014 ...
##  $ unemp_2015:'data.frame':  118 obs. of  8 variables:
##   ..$ Commune                   : chr [1:118] "Grand-Duche de Luxembourg" "Canton Capellen" "Dippach" "Garnich" ...
##   ..$ Total employed population : int [1:118] 233130 18310 1780 870 1470 4130 2170 1050 1300 3140 ...
##   ..$ of which: Wage-earners    : int [1:118] 212530 16430 1620 780 1350 3820 1910 920 1100 2770 ...
##   ..$ of which: Non-wage-earners: int [1:118] 20600 1880 160 90 120 310 260 130 200 370 ...
##   ..$ Unemployed                : int [1:118] 18806 988 106 29 73 260 80 41 72 169 ...
##   ..$ Active population         : int [1:118] 251936 19298 1886 899 1543 4390 2250 1091 1372 3309 ...
##   ..$ Unemployment rate (in %)  : num [1:118] 7.46 5.12 5.62 3.23 4.73 ...
##   ..$ Year                      : int [1:118] 2015 2015 2015 2015 2015 2015 2015 2015 2015 2015 ...
##  $ unemp_2016:'data.frame':  118 obs. of  8 variables:
##   ..$ Commune                   : chr [1:118] "Grand-Duche de Luxembourg" "Canton Capellen" "Dippach" "Garnich" ...
##   ..$ Total employed population : int [1:118] 236100 18380 1790 870 1470 4160 2160 1030 1330 3150 ...
##   ..$ of which: Wage-earners    : int [1:118] 215430 16500 1640 780 1350 3840 1900 900 1130 2780 ...
##   ..$ of which: Non-wage-earners: int [1:118] 20670 1880 150 90 120 320 260 130 200 370 ...
##   ..$ Unemployed                : int [1:118] 18185 975 91 27 66 246 76 35 70 206 ...
##   ..$ Active population         : int [1:118] 254285 19355 1881 897 1536 4406 2236 1065 1400 3356 ...
##   ..$ Unemployment rate (in %)  : num [1:118] 7.15 5.04 4.84 3.01 4.3 ...
##   ..$ Year                      : int [1:118] 2016 2016 2016 2016 2016 2016 2016 2016 2016 2016 ...

特別地,如果處理的數(shù)據(jù)是像unemployment數(shù)據(jù)這種,每個(gè)數(shù)據(jù)集的變量結(jié)構(gòu)一致,你可以在一次性導(dǎo)入同一目錄下所有數(shù)據(jù)文件的基礎(chǔ)上,利用rbind = TRUE選項(xiàng)將他們合并到一個(gè)數(shù)據(jù)集中:

bind_data <-  import_list(paths, rbind = TRUE)  
str(bind_data)
## 'data.frame':    472 obs. of  9 variables:
##  $ Commune                   : chr  "Grand-Duche de Luxembourg" "Canton Capellen" "Dippach" "Garnich" ...
##  $ Total employed population : int  223407 17802 1703 844 1431 4094 2146 971 1218 3002 ...
##  $ of which: Wage-earners    : int  203535 15993 1535 750 1315 3800 1874 858 1029 2664 ...
##  $ of which: Non-wage-earners: int  19872 1809 168 94 116 294 272 113 189 338 ...
##  $ Unemployed                : int  19287 1071 114 25 74 261 98 45 66 207 ...
##  $ Active population         : int  242694 18873 1817 869 1505 4355 2244 1016 1284 3209 ...
##  $ Unemployment rate (in %)  : num  7.95 5.67 6.27 2.88 4.92 ...
##  $ Year                      : int  2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
##  $ _file                     : chr  "data/unemployment/unemp_2013.csv" "data/unemployment/unemp_2013.csv" "data/unemployment/unemp_2013.csv" "data/unemployment/unemp_2013.csv" ...
 - attr(*, ".internal.selfref")=<externalptr> 

注意到新生成的數(shù)據(jù)集中多了一個(gè)變量:_file 用來(lái)指示當(dāng)前觀測(cè)原本屬于哪個(gè)數(shù)據(jù)文件。

  • 使用更多參數(shù)進(jìn)行非常規(guī)導(dǎo)入

如果數(shù)據(jù)導(dǎo)入遇到問(wèn)題,可能需要查看rio包背后使用的是什么包的什么函數(shù)來(lái)進(jìn)行數(shù)據(jù)導(dǎo)入,并根據(jù)情況在用import()讀取數(shù)據(jù)時(shí)添加對(duì)應(yīng)參數(shù)。
接下來(lái)看一個(gè)不成功的導(dǎo)入例子:

testdata <- import("data/mtcars_problem.csv")  
head(testdata)
##   mpg&cyl&disp&hp&drat&wt&qsec&vs&am&gear&carb
## 1          21&6&160&110&3.9&2.62&16.46&0&1&4&4
## 2         21&6&160&110&3.9&2.875&17.02&0&1&4&4
## 3        22.8&4&108&93&3.85&2.32&18.61&1&1&4&1
## 4      21.4&6&258&110&3.08&3.215&19.44&1&0&3&1
## 5       18.7&8&360&175&3.15&3.44&17.02&0&0&3&2
## 6       18.1&6&225&105&2.76&3.46&20.22&1&0&3&1

可以看出導(dǎo)入并不成功,不成功的原因在于原始的csv中使用非常規(guī)的“&”符號(hào)作為分隔符。查看import()的幫助(在R中運(yùn)行“?import”)可知,當(dāng)數(shù)據(jù)是csv格式時(shí),rio調(diào)用data.table包的fread()進(jìn)行讀取。我們進(jìn)一步查看data.table::fread()的幫助,發(fā)現(xiàn)fread()中可以使用sep=選項(xiàng)來(lái)指定csv數(shù)據(jù)的分隔符。當(dāng)我們把這個(gè)參數(shù)傳給import()后,import()會(huì)在調(diào)用data.table::fread()時(shí)將其傳給data.table::fread()

testdata <- import("data/mtcars_problem.csv", sep = "&")  
head(testdata)
##    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## 1   21   6  160 110  3.9  2.62 16.46  0  1    4    4
## 2   21   6  160 110  3.9 2.875 17.02  0  1    4    4
## 3 22.8   4  108  93 3.85  2.32 18.61  1  1    4    1
## 4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## 5 18.7   8  360 175 3.15  3.44 17.02  0  0    3    2
## 6 18.1   6  225 105 2.76  3.46 20.22  1  0    3    1
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容