
来源:大数据
本文约7100字,建议阅读15分钟。本文介绍了utils包在R语言基础的用途。
[ 导读 ]无论数据分析的目的是什么,将数据导入R中的过程都是不可或缺的。毕竟巧妇难为无米之炊。utils包是R语言的基础包之一。这个包最重要的任务其实并不是进行数据导入,而是为编程和开发R包提供非常实用的工具函数。使用utils包来进行数据导入和初步的数据探索也许仅仅只是利用了utils包不到1%的功能,但这1%却足以让你在学习R语言时事半功倍。
> flights "flights.csv")
此行代码可以解读为使用read.csv从工作空间读取文件flights.csv,然后将数据集保存到flights中,其他所有参数都使用默认值。因为flights.csv文件已经在R的工作路径里,所以此处免去了设置work directory。这里希望读者能够自行探索使用.rproj(R项目—将每一次数据分析的过程都看作一个独立的项目)来对每一个独立的数据分析工作进行分类和归集。该方法不仅免去了设置路径的麻烦,也减少了因原始数据文件太多而可能导致的各种隐患。小知识:函数在执行的时候可以依照其默认设置的参数位置来执行,也就是说,用户无须指定每一个参数的名称,只需按照位置顺序来设定参数值即可。比如,read.csv中的file参数名就可以省略,只要第一位是读取文档的目标路径和文件名就可以。数据文件被读取到R工作环境中的第一步通常为调用str函数来对该数据对象进行初步检视,下面的代码列出了该函数最简单的使用方式。
> str(object = flights)
'data.frame': 6 obs. of 6 variables:
$ carrier : Factor w/ 4 levels "AA","B6","DL",..: 4 4 1 2 3 4
$ flight : int 1545 1714 1141 725 461 1696
$ tailnum : Factor w/ 6 levels "N14228","N24211",..: 1 2 4 6 5 3
$ origin : Factor w/ 3 levels "EWR","JFK","LGA": 1 3 2 2 3 1
$ dest : Factor w/ 5 levels "ATL","BQN","IAH",..: 3 3 4 2 1 5
$ air_time: int 227 227 160 183 116 150
str函数可用于检视读取数据结构、变量名称等。这里同样也只指定了一个非默认参数,其他参数全部都为默认值。str的输出结果由5个主要部分组成,具体说明如下。data.frame代表数据集在R中的呈现格式,这里指的是数据框格式,读者可以将其设想为常见的Excel格式。
6 obs. of 6 variables代表这个数据集有6个变量,每个变量分别有6个观测值。
$ carrier与其余带有“$”符号的函数均指变量名称。
变量名称冒号后面的Factor和int代表的是变量类型。这里分别是指因子型Factor和整数型int数据。另外还有字符型chr、逻辑型logi、浮点型dbl(带有小数点的数字)、复杂型complex等。因子型变量的后面还列出了各个变量的因子水平,也就是拥有多少个不同的因子。比如,出发地origin后的3 levels就是表示其有3个因子水平。只是出发地是否属于因子类型的数据还有待商榷,而read.csv默认将所有的字符型数据都读成了因子型。
数据中的实际观测值。str函数在默认情况下会显示10行数据。使用str函数浏览导入的数据集可以让用户确定读取的数据是否正确、数据中是否有默认的部分、变量的种类等信息,进而确定下一步进行数据处理的方向。其他用来检视数据集的函数还有head、tail、view等,另外,Rstudio中的Environment部分也可以用于查看目前工作环境中的数据框或其他类型的数据集。
> flights1 "flights1.csv") > str(object = flights1) 'data.frame': 6 obs. of 1 variable:$ carrier.flight.tailnum.origin.dest.air_time: Factor w/ 6 levels "AA\t1141\tN619AA\tJFK\tMIA\t160",..: 4 6 1 2 3 5
小技巧:指定(assgin)符号“
由代码可知,read.csv函数将所有数据都读取到了一列中。因为按照默认的参数设置,函数会寻找逗号作为分隔列的标准,若找不到逗号,则只好将所有变量都放在一列中。指定分隔符参数可以解决这个问题。将\t(tab在R中的表达方式)指定给sep参数后再次运行read.csv读取以Tab分隔的csv文件,代码如下:
> flights3 "flights1.csv", sep = "\t")
> str(flights3)
'data.frame': 6 obs. of 6 variables:
$ carrier : Factor w/ 4 levels "AA","B6","DL",..: 4 4 1 2 3 4
$ flight : int 1545 1714 1141 725 461 1696
$ tailnum : Factor w/ 6 levels "N14228","N24211",..: 1 2 4 6 5 3
$ origin : Factor w/ 3 levels "EWR","JFK","LGA": 1 3 2 2 3 1
$ dest : Factor w/ 5 levels "ATL","BQN","IAH",..: 3 3 4 2 1 5
$ air_time: int 227 227 160 183 116 150
根据实际情况不同,字符型数据有时会是因子,有时不会。如果使用read.csv默认的读取方式,那么字符型全因子化会对后续的处理分析带来很多麻烦。所以最好是将字符因子化关掉。stringsAsFactors参数就是这个开关,示例代码如下:
> flights_str "flightsstrings.csv", sep = > str(object = flights_str) 'data.frame': 6 obs. of 6 variables:$ carrier : chr "UA" "UA" "AA" "B6" ...$ flight : int 1545 1714 1141 725 461 1696$ tailnum : chr "N14228" "N24211" "N619AA" "N804JB" ...$ origin : chr "EWR" "LGA" "JFK" "JFK" ...$ dest : chr "IAH" "IAH" "MIA" "BQN" ...$ air_time: int 227 227 160 183 116 150

> read.delim
function (file, header = TRUE, sep = "\t", quote = "\"", dec = ".",
fill = TRUE, comment.char = "", ...)
read.table(file = file, header = header, sep = sep, quote = quote,
dec = dec, fill = fill, comment.char = comment.char, ...)
<bytecode: 0x000000001a28a710>
<environment: namespace:utils>
无论是read.csv还是read.delim,帮助文档中的参数格式都是相同的。从上面的代码结果中可以看出,read.delim执行的其实,是函数read.table。
其实,这4个函数(read.csv/read.csv2/read.delim/read.delim2)都只是它们的母函数read.table的变形罢了。这样做的原因有可能是因为在RStudio出生之前,read.csv/delim比read.table更容易记住,也有可能只是Henrik Bengtsson(utils包的笔者)觉得这样做很酷。具体是什么原因已经不再重要,会用这些函数才是第一要务。3. read.table:任意分隔符数据读取read.table函数会将文件读成数据框的格式,将分隔符作为区分变量的依据,把不同的变量放置在不同的列中,每一行的数据都会对应相应的变量名称进行排放。以下简要列出了read.table函数中主要参数的中英文对照。函数read.table实用参数及功能对照:- file:数据文件路径+文件名,也可以是一个url,或者是文字数据 。
- header:设置逻辑值来指定函数是否将数据文件的第一列作为列名。默认为假。
- sep:不同变量之间的分隔符,特指分隔列数据的分隔符。默认值为空,可以是“,”、“\t”等。
- quote:单双引号规则的设置。如果不希望设置该参数,则需要指定其为空:quote = ""。
- dec:用作小数点的符号,一般为句点或者逗号。
- row.names:行名。可以通过指定一组向量来进行设置。如果文件中的第一行比数据整体的列数量少一时,则会默认使用第一列来作为行名。
- col.names:列名。可以通过指定一组向量来进行列名设置。
- na.strings:对默认值的处理。
- colClasses:变量类型的设置。通过指定一组向量来指定每列的变量数据类型,具体使用方式为:colClasses = c ("character","numeric",…)。
- fill:设置逻辑值来处理空白值部分,使用方法请参见代码演示部分。
- strip.white:设置逻辑值来处理空白列。某些数据文件内可能会预留一些变量列,但数据采集后这些预留的列并未被填满,而是仍然保留着制表符,该参数就是用来处理掉这些意义不大的制表符。
- blank.lines.skip:空白行是否跳过,默认为真,即跳过。
- stringsAsFactors:字符串是否作为因子,推荐设置为否。
- skip :跳过几行读取原始数据文件,默认设置为0,表示不跳过任何一行,从文件第一行开始读取,可以传参任意数字。
> flights "flights.csv")
> head(x = flights)
表1-2展示了所有参数均为默认设置的部分结果。- 表1-2 read.table函数参数设置结果展示①

> flights "flights.csv",header = TRUE)
> head(x = flights)
表1-3中显示的是部分结果。
- 表1-3 read.table函数参数设置结果展示②

> flights "flights.csv",header = TRUE,sep = ",")
> head(flights)
- 表1-4 read.table函数参数设置结果展示③


- 表1-5 特殊类型文本数据文档

> airlines <- read.table(file = "airlines.csv", header = TRUE, sep = "\t", blank.lines.skip = FALSE, stringsAsFactors = FALSE)
> head(airlines, n = 8)
指定空白行保留的参数后,数据被成功读进R(表1-6)。- 表1-6 read.table函数参数设置结果展示④

如果文件中开始的部分是暂时不需要的元数据,那么可以使用skip函数跳过相应的行数,只读取感兴趣的数据。
如果文件内容是一个整体,只是若干行数据具有额外的观测值。那么可以通过调整参数col.names或fill和header进行处理。
第一种情况比较容易,读者可以自行测试,在此略过。第二种情况需要知道数据中观测值个数的最大值,以用来补齐变量个数。因为已经知道airlines文件的第二部分拥有6个变量,所以下面就来演示如何将6个变量名称指定成新的变量名(表1-7),代码如下:
> airlines <- read.table(file = "airlines.csv", header = FALSE, sep = "\t", stringsAsFactors = FALSE, col.names = paste0("V",1:6), blank.lines.skip = FALSE)
> head(airlines)
演示结果如表1-7所示。- 表1-7 read.table函数参数设置结果展示⑤

但是在处理实际工作中成百上千行的数据时,这种手动指定变量个数的方法就显得笨拙而低效了。下面的代码演示了如何实现自动检测数据集所需的变量数:
> number_of_col <- max(count.fields("airlines.csv",sep = "\t"))
> airlines <- read.table(file = "airlines.csv", header = FALSE, sep = "\t", stringsAsFactors = FALSE, col.names = paste0("V",seq_len(number_of_col)), blank.lines.skip = FALSE)
> head(airlines)
部分结果展示如表1-8所示。- 表1-8 read.table函数参数设置结果展示⑥

> flights_uneven <- read.table("airlines.csv", header = FALSE, sep = "\t", stringsAsFactors = FALSE, fill = TRUE)> head(flights_uneven)
上述代码的演示结果如表1-9所示。- 表1-9 read.table函数参数设置结果展示⑦

> flights_uneven <- read.table(file = "flights_uneven.csv", header = FALSE, sep = "\t", stringsAsFactors = FALSE, fill = TRUE, na.strings = c(""))
> head(flights_uneven)
表1-10中展示了处理后的部分数据值。表1-10 read.table函数参数设置结果展示⑧

> flights_uneven "flights_uneven.csv",sep = > head(flights_uneven)
替换结果如表1-11所示。- 表1-11 read.table函数参数设置结果展示⑨

> flights_uneven "flights_uneven.csv",sep = "\t", string-sAsFactors = FALSE, fill = TRUE, header = FALSE)
> replace
replace
[1] "" "测试1" "测试2" "测试3"
> flights_uneven "flights_uneven.csv",sep = "\t", stringsAsFactors = FALSE, fill = TRUE,header = FALSE, na.strings = c(replace[c(1,3)]))
> head(flights_uneven)
替换结果如表1-12所示。- 表1-12 read.table函数参数设置结果展示⑩

小知识:“[”是baseR中Extract的一种,在R的使用过程中,这是必须掌握和理解的函数之一。
编辑:王菁
校对:林亦霖