【2.1】R读写数据

一、读数据

R在读取数据的时候针对不同的数据有不同的读取方法:

read.table, read.csv, for reading 表格数据
readLines 读取text的各行,类似perl读数据方式。
source 读取R命令文件(inverse of dump)
dget 读取R命令文件(inverse of dput)
load 导入保存保存的工作路径<!-- more -->unserialize for reading single R objects in binary form
scan( ):将数据读作一行向量形式。
read.delim("educ_scores.txt"):读入文本文件(制表符分隔)。
read.csv("educ_scores1.csv"):读入CSV(逗号分割)。
readBin( ):读入二进制数据。
readChar( ):读入字符型数据。
attach( ): 把数据框的变量链接到内存中.

1.1 read.table

read.table()
Reads a file in table format and creates a data frame from it, with cases corresponding to lines and variables to fields in the file.
根据数据行和列读成数据矩阵。

是读取数据中最广泛使用的

 read.table(file, header = FALSE, sep = "", quote = ""'",
 dec = ".", row.names, col.names,
 as.is = !stringsAsFactors,
 na.strings = "NA", colClasses = NA, nrows = -1,
 skip = 0, check.names = TRUE, fill = !blank.lines.skip,
 strip.white = FALSE, blank.lines.skip = TRUE,
 comment.char = "#",
 allowEscapes = FALSE, flush = FALSE,
 stringsAsFactors = default.stringsAsFactors(),
 fileEncoding = "", encoding = "unknown")
 file 文件的名字,或者是一个链接
 header:逻辑参数。指定是否文件第一行为变量名。
 na.strings:指定缺失文字。
 skip:指定读数据跳过的行数。
 nrows:指定数据读入最大的行数。
 dec:指定小数点记号。
 sep:指定数据分割字符。
 row.names与col.names:赋予数据行名和列名。
 colClasses 数据中每列的类型
 comment.char 注释字符
 stringsAsFactors字符变量是否变为因子

例如:下面的三个都可以

> read.table("qiuworld.com.txt",header=TRUE,sep="\t",quote="",comment.char="#")
 > read.delim("qiuworld.com.txt",header=TRUE,sep="\t",quote="",comment.char="#")
 > read.csv("qiuworld.com.txt",header=TRUE,sep="\t",quote="",comment.char="#")

如果只读取前5行,可以这样:

 > read.delim("qiuworld.com.txt",comment.char="#",nrows=5)
 读第3段开始的5段
 > read.delim("qiuworld.com.txt",header=F,nrows=5,skip=3)

注释

默认情况下,read.table 用 # 作为注释标识字符。如果碰到该字符(除了在被引用的字符串内),该行中随后的内容将会被忽略。只含有空白和注释的行被当作空白行。

如果确认数据文件中没有注释内容,用 comment.char = "" 会比较安全 (也可能让速度比较快)。

read.table常见的问题:

1.1 编码问题

如果文件中包含非-ASCII字符字段,要确保以正确的编码方式读取。这是在UTF-8的本地系统里面读取Latin-1文件的一个主要问题。此时,可以如下处理

read.table(file(“file.dat”, encoding=“latin1”))

注意,这在任何可以呈现Latin-1名字的本地系统里面运行。

1.2 首行问题

我们建议你明确地设定 header 参数。按照惯例,首行只有对应列的字段而没有行标签对应的字段。因此,它会比余下的行少一个字段。(如果需要在 R 里面看到这一行,设置 header = TRUE。)如果要读取的文件里面有行标签的头字段(可能是空的),以下面的方式读取

read.table(“file.dat”, header = TRUE, row.names = 1)

列名字可以通过 col.names 显式地设定;显式设定的名字会替换首行里面的列名字(如果存在的话)。

1.3 分隔符问题

通常,打开文件看一下就可以确定文件所使用的字段分隔符,但对于空白分割的文件,可以选择默认的sep = "" (它能使用任何空白符作为分隔符,比如空格,制表符,换行符), sep = " " 或者 sep = “\t”。注意,分隔符的选择会影响输入的被引用的字符串。 如果你有含有空字段的制表符分割的文件,一定要使用 sep = “\t”。

1.4 引用

默认情况下,字符串可以被 " 或 ' 括起,并且两种情况下,引号内部的字符都作为字符串的一部分。有效的引用字符(可能没有)的设置由参数 quote 控制。对于sep = “\n”,默认值改为 quote = “"。 如果没有设定分隔字符,在被引号括起的字符串里面,引号需要用 C格式的逃逸方式逃逸,即在引号前面直接加反斜杠 \。 如果设定了分隔符,在被引号括起的字符串里面,按照电子表格的习惯,把引号重复两次以达到逃逸的效果。例如

‘One string isn'’t two’,“one more”

可以被下面的命令读取

read.table(“testfile”, sep = “,")

这在默认分隔符的文件里面不起作用。

1.5缺损值

默认情况下,文件是假定用 NA 表示缺损值,但是,这可以通过参数 na.strings 改变。参数 na.strings 是一个可以包括一个或多个缺损值得字符描述方式的向量。 数值列的空字段也被看作是缺损值。

在数值列,值 NaN,Inf 和 -Inf 都可以被接受的。

1.6 尾部空字段省略的行

从一个电子表格中导出的文件通常会把拖尾的空字段(包括?堑姆指舴? 忽略掉。为了读取这样的文件,必须设置参数 fill = TRUE。

1.7 字符字段中的空白

如果设定了分隔符,字符字段起始和收尾处的空白会作为字段一部分看待的。为了去掉这些空白,可以使用参数 strip.white = TRUE。

1.8 空白行

默认情况下,read.table 忽略空白行。这可以通过设置 blank.lines.skip = FALSE 来改变。但这个参数只有在和 fill = TRUE 共同使用时才有效。这时,可能是用空白行表明规则数据中的缺损样本。

1.9 变量的类型

除非你采取特别的行动,read.table 将会为数据框的每个变量选择一个合适的类型。如果字段没有缺损以及不能直接转换,它会按 logical, integer, numeric 和 complex 的顺序依次判断字段类型。如果所有这些类型都失败了,变量会转变成因子。

参数 colClasses 和 as.is 提供了很大的控制权。 as.is 会 抑制字符向量转换成因子(仅仅这个功能)。 colClasses运行为输入中的每个列设置需要的类型。

注意,colClasses 和 as.is 对每 列专用,而不是每个变量。因此,它对行标签列也同样适用(如果有的话)。

1.10 注释

默认情况下,read.table 用 # 作为注释标识字符。如果碰到该字符(除了在被引用的字符串内),该行中随后的内容将会被忽略。只含有空白和注释的行被当作空白行。

如果确认数据文件中没有注释内容,用 comment.char = "” 会比较安全 (也可能让速度比较快)。

1.11 逃逸

许多操作系统有在文本文件中用反斜杠作为逃逸标识字符的习惯,但是Windows系统是个例外(在路径名中使用反斜杠)。在 R 里面,用户可以自行设定这种习惯是否用于数据文件。

read.table 和 scan 都有一个逻辑参数 allowEscapes。从 R 2.2.0 开始,该参数默认为否,而且反斜杠是唯一被解释为逃逸引用符的字符(在前面描述的环境中)。如果该参数设为是,以C形式的逃逸规则解释,也就是控制符如 \a, \b, \f, \n, \r, \t, \v,八进制和十六进制如 \040 和 \0x2A 一样描述。任何其它逃逸字符都看着是自己,包括反斜杠。

读取粘贴板中的数据

先将数据ctrl +c 复制,然后

aa <- read.table(file='clipboard',header = FALSE)
as.data.frame(table(aa))  #返回矩阵,第一列levels 第二列频数freq

1.2 read.csv

arc<-read.csv("/sam/abd/arc_classified.csv",header=TRUE,sep="\t",quote="",comment.char="#",as.is = T);
arc<-read.csv("/sam/abd/arc_classified.csv",header=TRUE,sep="\t",quote="",comment.char="#") 
<strong>read.csv的一个特性是会自动地将非数值类型的数据视为因子(factor),即分类变量</strong>。但在某些情况下,也有可能确实需要字符串,而不是因子。把<strong>as.is参数设为TRUE即可,此时R就不会将分数值数据视为因子。</strong>
comment.char="#" 忽略#的行,comment.char=""可以禁用。str(arc$family.n) #查看数据类型。
 方法1读入的百分数为chr,方法2读入的百分数为factor

1.3 scan

问题是,以上的文件都是格式化的表格文件。如果文件并非表格式文件,而是一些的字符或者数字,并且每行长度不同呢?我们可以使用scan来输入。

scan()

Read data into a vector or list from the console or file.

读成向量或列表

> scan("qiuworld.com.txt",what=character(),sep="\t",fill=F,comment.char="#")
 Read 27 items
 [1] "ArrayDataFile" "SourceName" "FactorValue" "GSM286765.CEL" "t_24h_rep1" "treated_24h"
 [7] "GSM286759.CEL" "t_12h_rep1" "treated_12h" "GSM286763.CEL" "c_24h_rep2" "control_24h"
 [13] "GSM286760.CEL" "t_12h_rep2" "treated_12h" "GSM286757.CEL" "c_12h_rep2" "control_12h"
 [19] "GSM286766.CEL" "t_24h_rep2" "treated_24h" "GSM286756.CEL" "c_12h_rep1" "control_12h"
 [25] "GSM286762.CEL" "c_24h_rep1" "control_24h"
 >scan("qiuworld.com.txt",what=list(ArrayDataFile=character(),SourceName=character(),FactorValue=character()),skip=2,nlines=5,comment.char="#")
 Read 5 records
 $ArrayDataFile
 [1] "GSM286765.CEL" "GSM286759.CEL" "GSM286763.CEL" "GSM286760.CEL" "GSM286757.CEL"
$SourceName
 [1] "t_24h_rep1" "t_12h_rep1" "c_24h_rep2" "t_12h_rep2" "c_12h_rep2"
$FactorValue
 [1] "treated_24h" "treated_12h" "control_24h" "treated_12h" "control_12h"

1.4 read.DNAStringSet

读入sequence文件(比如fasta, fastq, BAM, gff, bed, 或者 wig)

 > library("Biostrings")
 > read.DNAStringSet("qiuworld.com.fasta")

一些小点的数据集,可以省略上面的一些参数

data <- read.table("foo.txt")

 R会自动的进行:
 跳过以#开始的行;
 计算多少行,以及需要多少内存;
 每一列的变量类型;
 如果通过参数告诉R可以让R运行的更快一些
 read.csv跟read.table一样,除了默认的分隔符是逗号

1.5 readLines

readLines功能可以用来简单的读取文本文件的行,然后通过字符向量来存储他们

> con <- gzfile("words.gz")
> x <- readLines(con, 10)
> x
[1] "1080" "10-point" "10th" "11-point"
[5] "12-point" "16-point" "18-point" "1st"
[9] "2" "20-point"

readLines也可以用来读取网页的每一行
## This might take time
con <- url("http://www.jhsph.edu", "r")
x <- readLines(con)
> head(x)
[1] ""
[2] ""
[3] ""
[4] ""
[5] "\t

1.6 file

数据通过连接接口被读取,链接可以指向文件也可以是其他的东西。

file, opens a connection to a file
gzfile, opens a connection to a file compressed with gzip
bzfile, opens a connection to a file compressed with bzip2
url, opens a connection to a webpage
>** str(file)**
function (description = "", open = "", blocking = TRUE,
encoding = getOption("encoding"))
description是文件的名字
open预示文件的类型
“r” read only
“w” writing (and initializing a new file)
“a” appending
“rb”, “wb”, “ab” reading, writing, or appending in binary mode (Windows)

一般情况下,connections是一个非常强大的工具,可以让你找到文件,并连接到上面去,但实际中,我们并没有必要通过它来,可以直接读取数据。

con <- file("foo.txt", "r") #通过con先连接数据
data <- read.csv(con)
close(con)

也可以这样

data <- read.csv("foo.txt")

1.7 dput与dget

用dput来deparsing the R object,dget来读取它

> y <- data.frame(a = 1, b = "a")
> dput(y)
structure(list(a = 1,
b = structure(1L, .Label = "a",
class = "factor")),
.Names = c("a", "b"), row.names = c(NA, -1L),
class = "data.frame")
> dput(y, file = "y.R") #给文件命令了,否则就像上面的在终端显示
> new.y <- dget("y.R") #用dget来读取
> new.y
a b
1 1 a

1.8 dump与source

同的对象可以用dump来deparsed,然后用source来读取。

> x <- "foo"
> y <- data.frame(a = 1, b = "a")
> dump(c("x", "y"), file = "data.R")
> rm(x, y)
> source("data.R")
> y
a b
1 1 a
> x
[1] "foo"

注意:

对于很大的数据来说,下面的一些提示可以对于有一些帮助:

  1. 认真读一下 read.table的帮助说明
  2. 粗略的计算一下需要多少内存来存储你的数据,如果数据大于你计算机的RAM,那你可以立马停止工作了。

内存是多大?

那些应用正在使用

其他的用户有没有在使用?

你的系统是啥子? >st r(.Platform)

32位还是64位捏? >version

计算内存:

I have a data frame with 1,500,000 rows and 120 columns, all of which are numeric
data. Roughly, how much memory is required to store this data frame?
1, 500, 000 * 120 *8 bytes/numeric = 1440000000 bytes
= 1440000000/220 bytes/MB
= 1, 373.29 MB
= 1.34 GB

3.如果没有注释行,设置comment.char = "”

4,使用colClasses参数,而不是使用默认值可以让 ’read.table’运行的更快,一般速度提升一倍哦.如果使用这个参数的话,你就必须知道每列的类别。如果所有的列都是数字类型,你可以设置colClasses = “numeric”。你可以用这个方法知道每一列是什么类型:

initial <- read.table("datatable.txt", nrows = 100)
classes <- sapply(initial, class)
tabAll <- read.table("datatable.txt",colClasses = classes)

5,设置nrows参数,这个参数不能使R变快,但是能节约内存,你可以使用 Unix工具wc来计算这个文件的行数

二 、写数据

write.table
writeLines
dump
dput
save
serialize

2.1 write.table

write.table(df, file="file_name.txt", quote=FALSE, sep = " ", row.names=FALSE)

以数据框为例:

 df 是数据框对象
 file 文件名(没有路径的话直接保存在当前工作目录下,getwd()查看工作目录)
 quote 是否在数据上添加引号,(默认是TRUE,添加引号的)
 sep 是字段分隔符,默认是空格(“\t”是制表符号,如果需要复制粘贴到表格中,则用制表符)
 row.names 是否显示记录名称,没有特别的名称的话,是 1,2,3,4

完整用法

 write.table(x, file = "", append = FALSE, quote = TRUE, sep = " ",
 eol = "\n", na = "NA", dec = ".", row.names = TRUE,
 col.names = TRUE, qmethod = c("escape", "double"),
 fileEncoding = "")

append = TRUE, 如果文件夹中已有相同的名字,则自动扩展, append = FALSE,如果文件夹中已有相同的名字,则覆盖同名的文件, 总之,在使用处理大数据之前,你需要知道你系统的一些信息

2.2 writeLines

读取字符向量然后每个元素一行的来写入文本文件中

注:

文本格式

dumping和dputing非常有用,因为结果文本格式是可编辑的,同时如果崩溃后也是可能找回来的。 跟table或csv不一样,dump和dput保存了宏数据(牺牲了一些可读性),这样其他的用户就没有必要重复的制定数据了

文本格式比只能在文本文件中跟踪改变的控制程序(例如subversion or git)更方便一些

文本格式可以长久保存,如果某个地方有问题,也方便修改

文本格式Unix philosophy紧密相连

但是呢文本格式不是太节约空间。

R从使用分界符的文本(delimited text)读取数据到数据框的命令为read.table()。关于此文本的格式,有以下要求: 行的分界符为换行/回车,列的分界符为空格或制表符(TAB)。 特别注意,R把任意多个连续的空格或制表符只算作一个。

由于R把连续空格或制表符只算作一个,如果数据表中有空缺的单元格,将会导致R读入时列发生错位。 如果数据表中有空缺的单元格,一定要用NA来表示缺失的数据,否则将会导致读入数据错位。 一般来说第一行用来存放变量名。如果第一行不是变量名,R用“V1, V2, …”来命名变量。 为了以后方便地跟踪数据,应当设置ID列。一般来说第一列用来存放ID。 如果变量名比数据列少一个,R将假定第一列为ID列。

三、删除数据

file.remove("gc.pdf")

四、Excel的处理

install.packages("readxl")
library(readxl)
samples = read_excel('v:\\data/We/reference/20170330样本信息.xlsx','analysis')

参考资料

药企,独角兽,苏州。团队长期招人,感兴趣的都可以发邮件聊聊:tiehan@sina.cn
个人公众号,比较懒,很少更新,可以在上面提问题,如果回复不及时,可发邮件给我: tiehan@sina.cn