R语言笔记之数据的导入与导出

数据的导入

在R语言中,常常用到导入数据的源文件是Excel文件,CSV文件,文本文件等等。

R中有关数据读入的函数包括:read.csv()read.delim()read.delim2()read.table()data.table::fread()(双冒号表示的是data.table包中的fread()函数)。

read.csv()——导入csv文件

此方法可以用以导入Excel数据,将Excel数据转化为csv格式。
CSV是(逗号分隔值)的英文缩写,通常都是纯文本文件。

其导入R中的数据格式为:

1
2
3
4
5
6
mydataframe<-read.table(file,header=logical_value,ep="delimiter",row.names="name")
file:csv文件
header:逻辑值,首先是否包括变量名
sep:分隔符
row.names:指定一个或多个表示行标识符的变量
grades<-read.table("studentgrades.csv",header=TRUE,sep=",",row.names="STUDENTID")

表示从当前目录中读取一个名为studentgrades.csv的逗号分隔文件,从文件的第一行取得变量名字,将STUDENTID指定为行标识符,整个结果保存到grades的数据框中。

read.csv()

另外一个导入csv文件的函数是read.csv()

read.delimread.delim2

这两个函数可以分别使用句号逗号作为小数位来导入制表符分隔的文件。

导入剪切板中的数据

通常情况下就是在Excel中复制,接着输入以下命令就可以导入数据。

1
data <- read.table("clipboard", header = T, sep="\t")

导入文本文件

一般采用read.table()函数和read.csv()函数实现文本文件数据的读取,对于这两个函数有几个重要的参数:

  1. file指定外部文件的路径和文件名;
  2. header指定是否将原数据的第一行最为字段名,read.table()函数默认设置为FALSE,而read.csv()函数默认设置为TRUE;
  3. sep指定字段之间的分割符,read.table()函数默认设置为空格””,而read.csv()函数默认设置为逗号;
  4. 除此,read.table()函数还可以设置读入数据集的行名、列名、字符串是否转换为因子、缺失值的形式等,详细可查看read.table()函数的帮助文档。

从scan导入数据

主要用于键盘输入数据,详细使用方法:

scan() 函数

1
2
3
4
5
6
scan(file = "", what = double(0), nmax = -1, n = -1, sep = "",
     quote = if(identical(sep, "\n")) "" else "'\"", dec = ".",
     skip = 0, nlines = 0, na.strings = "NA",
     flush = FALSE, fill = FALSE, strip.white = FALSE,
     quiet = FALSE, blank.lines.skip = TRUE, multi.line = TRUE,
     comment.char = "", allowEscapes = FALSE, encoding = "unknown")

参数使用如下所示:

  1. what:声明读入为字符类型数据,可能指定读入的精度/类型,例如:what=integer(0);what=numeric(0);what=character(0);
    如果SCAN()读入有字符与数字,用what=””来进行声明,则会把读入的数字隐式的都转变成字符;
  2. sep:指定各个读入的数据之间的分隔符;默认情况下分隔符:空格、tab;如果不是其它分隔符,例如“:/”通过SEP来指定;
  3. 可以通过list指定读入变量的变量名,同时生成的对象为列表,则可以同时读入字符与数字;
  4. Skip 从第几行开始读入数据;
  5. Nlines 指定最大读入行数;
  6. 如果通过键盘输入的时候,不希望出现下标提示,则可以使用:quiet=TRUE;
  7. encoding =””指定的编码格式,有时候读入的中文可能会出现乱码的时候,可能通过这个参数来指定:Latin-1 或者 UTF-8

使用表格输入数据

1
2
3
4
mydata<-data.frame(age=numeric(0),
                   gender=character(0),
                   weight=numeric(0))
mydata<-edit(mydata)

创建一个名为mydata的数据框,含三个变量,age为数据型,gender为字符型,weight为数值型。edit调用文本编辑器,键入数据。其中numeric(0)创建一个指定模型但不含实际数据的变量。如果再次调用mydata<-edit(mydata)能够用来修改数据,或者使用fix(mydata)也行。

使用readxl包来读取excel文件

readxl包中的几个函数可以读取excel文件,主要有read_excelread_xlsread_xlsx。其中各个函数的参数如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
read_excel(path, sheet = NULL, range = NULL, col_names = TRUE,
col_types = NULL, na = "", trim_ws = TRUE, skip = 0,
n_max = Inf, guess_max = min(1000, n_max),
progress = readxl_progress(), .name_repair = "unique")
read_xls(path, sheet = NULL, range = NULL, col_names = TRUE,
col_types = NULL, na = "", trim_ws = TRUE, skip = 0,
n_max = Inf, guess_max = min(1000, n_max),
progress = readxl_progress(), .name_repair = "unique")
read_xlsx(path, sheet = NULL, range = NULL, col_names = TRUE,
col_types = NULL, na = "", trim_ws = TRUE, skip = 0,
n_max = Inf, guess_max = min(1000, n_max),
progress = readxl_progress(), .name_repair = "unique")

参数意义如下所示:

参数 含义
path xls/xlsx文件的路径
sheet Excel文件中Sheet的参数,可以是一个字符串,也就是sheet的名称,可以是一个整数,它表示sheet的位置。如果不输入这个参数,默认输入第1个sheet的数据。
range sheet中单元格的范围,例如可以输入range=B2:G14。也可以指定某个sheet,例如range="mtcars!B1:D5"
col_names TRUE 使用第一行作为行名, FALSE 使用默认的名字,或者是使用一个字符串或字符串向量来表示第一行的名称。
col_types Either NULL to guess all from the spreadsheet or a character vector containing one entry per column from these options: “skip”, “guess”, “logical”, “numeric”, “date”, “text” or “list”. If exactly one col_type is specified, it will be recycled. The content of a cell in a skipped column is never read and that column will not appear in the data frame output. A list cell loads a column as a list of length 1 vectors, which are typed using the type guessing logic from col_types = NULL, but on a cell-by-cell basis.
na Character vector of strings to interpret as missing values. By default, readxl treats blank cells as missing data.
trim_ws Should leading and trailing whitespace be trimmed?
skip Minimum number of rows to skip before reading anything, be it column names or data. Leading empty rows are automatically skipped, so this is a lower bound. Ignored if range is given.
n_max Maximum number of data rows to read. Trailing empty rows are automatically skipped, so this is an upper bound on the number of rows in the returned tibble. Ignored if range is given.
guess_max Maximum number of data rows to use for guessing column types.
progress Display a progress spinner? By default, the spinner appears only in an interactive session, outside the context of knitting a document, and when the call is likely to run for several seconds or more. See readxl_progress() for more details.
.name_repair Handling of column names. By default, readxl ensures column names are not empty and are unique. If the tibble package version is recent enough, there is full support for .name_repair as documented in tibble::tibble(). If an older version of tibble is present, readxl falls back to name repair in the style of tibble v1.4.2.

具体的可以参考readxl资料

批量读取数据

读取N个Excel文件,并将这N个Excel文件进行合并,分为四种情况,代码如下所示,其中read_excel函数所在的包为readxl。

解决方案如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
setwd('D:\\data file\\data1')
# 设置R的工作空间
#res <- NULL
data1 <- data.frame()
# 初始化数据框,用于后面的数据合并
#通过循环完成数据合并
for (i in 1:4){
path <- paste0(getwd(),'\\','test',i,'.xlsx') # 构造数据路径
res <- c(res,path)
data1 <- rbind(data1,read_excel(path = path)) # 读取并合并数据
}

对于文件没有规律的情况,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
setwd('D:\\data file\\data2') # 设置工作空间
filenames <- dir() # 读取该工作空间下的所有文件名
data2 <- data.frame() # 初始化数据框,用于后面的数据合并
#通过循环完成数据合并
for (i in filenames){
# 构造数据路径
path <- paste0(getwd(),'\\',i)
#res <- c(res,path)
# 读取并合并数据
data2 <- rbind(data2,read_excel(path = path))
}

对于文件名没有规律的情况,并且只读取某做后缀的文件,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 加载第三方扩展包,用于编写SQL语句
library(sqldf)
# 设置工作空间
setwd('D:\\data file\\data4')
# 读取该工作空间下的所有文件名
filenames <- dir()
# 通过正则,获取所有xlsx结尾的文件名
filenames2 <- grep('\\.xlsx', filenames, value = TRUE)
# 初始化数据框,用于后面的数据合并
data4 <- data.frame()
#通过循环完成数据合并
for (i in filenames2){
# 构造数据路径
path <- paste0(getwd(),'\\',i)
#res <- c(res,path)
# 使用read_excel函数读取xlsx文件
data <- read_excel(path = path)
# 使用sqldf函数编写SQL语句,并把结果合并起来
data4 <- rbind(data4, sqldf("select id,name,gender,age from data"))
}

导出数据

导出的路径

为了避免在导出路径中使用转义字符,可以使用file.path()函数来构建正确的路径,这个函数的工作原理类似于paste(),如下所示:

1
2
file.path("d:","download")
[1"d:/download"

file.path(“d:”,”download”)
[1] “d:/download”

导出为txt格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 a
[1]  1  2  4 NA  5  4
> b
[1"a" "b" "c" "d" NA  "4"
 c <- data.frame(a,b)
 c
   a    b
1  1    a
2  2    b
3  4    c
4 NA    d
5  5 <NA>
6  4    4
 write.table(c,file = "c:\\data.txt",sep = ",",quote = FALSE, append = FALSE, na = "NA")

c为导出的数据,file为导出的路径,sep = “,”表示用逗号隔开数据,quote = FALSE表示消除字符串的引号标志,append = FALSE打开一个新文件,如果为TRUE则表示将此数据追加到已经存在的文件中,na=”NA”表示用NA来代表na值。

读取错误

R语言读取Excel文件有时会出错,如果要读取某些Excel表格文件,操作如下所示:

  1. 用鼠标选中据,然后Ctrl+C复制;
  2. 在Rstudio中输入:read.table(“clipboard”,header=T)->x1,显示以下结果:

Error in scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings, :
line 2 did not have 8 elements

大概意思是,有两行数据的元素不满足8个(即第No.2不满足8个元素),无法读取,因此需要改变一下代码,如下所示:

1
x <- read.table("clipboard",sep="\t",header=T)

这样就能正常读取了,因为Excel的文件中,每个单元格就是以制表符将它们分开的,而sep=“\t”的意思就是,读取数据的时候,以制表符进行分割来读取。

R语言与目录操作

设置目录file.path()

在R中,目录的表达方法与Windows有所不同,在Windows中,如果要表示D盘下的某个目录,就是D:\biotest,用的是\,而在R中,则是/\\,即D:/biotestD:\\biotest。为了避免在R中使用转义字符,可以使用file.path()函数来构建正确的路径。这个函数类似于paste(),会将传入的各个参数拼接在一起,与操作系统的设置无关,如下所示:

1
2
> file.path("D:","biotest")
[1] "D:/biotest"

使用file.path()来设置工作目录非常方便,可以逐一指定目录,它会将各个目录连接起来,如下所示:

1
2
3
4
5
> getwd()
[1] "D:/"
> setwd(file.path("D:","biotest"))
> getwd()
[1] "D:/biotest"

操作文件dir()list.files()

有的时候,在R中如果要遍历某个指定目录下的所有文件和文件夹,并对它们进行某种操作,如果要获得指定目录下的文件列表,可以使用list.files()dir()函数,这两个函数的功能是一样的,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> getwd()
[1] "D:/biotest"
> list.files()
[1] "kegg"
[2] "Miniconda2-latest-Linux-x86_64.sh"
[3] "NGS 数据过滤之 Trimmomatic 详细说明 - 简书.pdf"
[4] "nohup.out"
[5] "paper and manual"
... ...
> dir()
[1] "kegg"
[2] "Miniconda2-latest-Linux-x86_64.sh"
[3] "NGS 数据过滤之 Trimmomatic 详细说明 - 简书.pdf"
[4] "nohup.out"
[5] "paper and manual"
... ...

也可以查看某个特定文件夹的内容:

1
2
3
4
5
6
7
> dir(file.path("D:","biotest","kegg"))
[1] "eco00640.eco.kegg.png"
[2] "eco00640.png"
[3] "eco00640.xml"
[4] "hsa00640.gene.ensprot.cpd.cas.png"
[5] "hsa00640.gene.entrez.cpd.kc.png"
... ...

返回文件目录dirname与文件名basename

dirname函数只返回文件目录,不返回文件名,而basename函数与之相反,只返回文件名,不返回言论的目录,如下所示:

1
2
3
4
5
6
7
> file_name <- "C:/Program Files/R/R-devel/bin/x64/RGui.exe"
> file_name
[1] "C:/Program Files/R/R-devel/bin/x64/RGui.exe"
> basename(file_name)
[1] "RGui.exe"
> dirname(file_name)
[1] "C:/Program Files/R/R-devel/bin/x64"

文件操作函数汇总

常用的几个操作文件以及目录的函数,如下所示:

函数 说明
list.files 列出某个目录下的所有文件
list.dirs 列出某个目录下的所有子目录
file.exists 检查某个特定的文件是否存在于某个目录下
file.create 创建一个空文件
file.rename 重命名文件
file.copy 复制文件
file.remove 删除文件
unlink 删除目录,例如unlink("tmp", recursive=F) #如果文件夹tmp为空,删除文件夹tmp;unlink("tmp", recursive=TRUE)#删除文件夹tmp,如果其中有文件一并删除
file_test() 判断一个对象是目录还是文件,-f为判断文件,-d是判断目录,语法格式为:file_test("-f", "test")
tempfile 返回一个临时文件的名称,例如想要在临时文件夹中创建一个文件,就可以将这个函数的返回值传入file.create()write.table()函数中
tempdir 返回文件系统中临时文件目录的路径。
dir.create 创建一个文件夹或目录,如果要创建多个目录recursive = TRUE
getwd() 获取当前目录
setwd() 设置工作目录
choose.dir() 以窗口的形式设置工作目录
dir() 查看当前目录的子目录和文件,功能与list.files()相同

文件操作案例

现在创建一个临时文件,并将iris数据框传入其中,然后为了测试数据是否已经写入,再读取这个文件,并将结果保存到一个变量中,然后检查这个变量,最后将这个临时文件删除。

第一步,使用tempfile()函数得到一个字符串,它表示系统临时目录中的一个临时文件,如下所示:

1
2
my.file <- tempfile()
my.file

运行结果如下所示:

1
2
3
> my.file <- tempfile()
> my.file
[1] "C:\\Users\\Public\\Documents\\Wondershare\\CreatorTemp\\RtmpCWS6Kb\\file26fc52842c9e"

结果返回的是一个字符串,而不是文件,其实文件并不存在,现在通过write.csviris写入到my.file,然后使用list.files()来查看R创建的文件,如下所示:

1
2
write.csv(iris,file=my.file)
list.files(tempdir())

运行结果如下所示:

1
2
3
4
5
6
7
> write.csv(iris,file=my.file)
> list.files(tempdir())
[1] "file26fc25291904"
[2] "file26fc52842c9e"
[3] "libloc_185_b6156d26.rds"
[4] "libloc_196_12ea9df4.rds"
[5] "rs-graphics-c18658be-c44b-4ca8-b450-15a567601981"

其中,file26fc52842c9e是临时文件,使用read.csv将文件导入到一个名为file.iris的变量中,并使用str()查看,如下所示:

1
2
file.iris <- read.csv(my.file)
str(file.iris)

运行结果如下所示:

1
2
3
4
5
6
7
8
9
> file.iris <- read.csv(my.file)
> str(file.iris)
'data.frame': 150 obs. of 6 variables:
$ X : int 1 2 3 4 5 6 7 8 9 10 ...
$ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
$ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
$ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
$ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
$ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...

最后为了恢复文件系统原来的状态,使用file.remove()删除这个临时文件,如下所示:

1
2
file.remove(my.file)
list.files(tempdir())

结果如下所示:

1
2
3
4
5
> list.files(tempdir())
[1] "file26fc25291904"
[2] "libloc_185_b6156d26.rds"
[3] "libloc_196_12ea9df4.rds"
[4] "rs-graphics-c18658be-c44b-4ca8-b450-15a567601981"

file26fc52842c9e这个文件已经被删除了。

参考资料

  1. R语言轻松入门与提高 [法]Andrie de Vries ,[比利时]Joris Mey
  2. 学习R.[美] Richard,Cotton 著刘军 译
  3. R语言目录及文件操作
  4. R语言-文件管理系统操作