R语言 数据框、矩阵、列表的创建、修改、导出

2023-01-06 22:32:50 浏览数 (1)

数据框

数据框的创建

数据框来源主要包括用代码新建(data.frame),由已有数据转换或处理得到(取子集、运算、合并等操作),读取表格文件(read.csv,read.table等)及R语言内置数据

函数data.frame生成指定数据框的列名及列的内容,如代码所示,此时列名不需添加"",df1为变量名,格式为列名=列的向量

*matrix矩阵与向量一样只允许同一种数据类型,否则会被转换,可以理解为二维的向量,data.frame数据框允许不同列不同的数据类型,但同一列只允许一种数据类型

*数据框中括号内行在列前

代码语言:javascript复制
df1 <- data.frame(gene   = paste0("gene",1:4),
                 change  = rep(c("up","down"),each = 2),
                 score   = c(5,3,-2,-4))
df1

数据框通过csv及txt导入

*csv文件可用excel打开(直接打开),记事本打开,或用R语言读入,读入后进行的修改不会同步到表格文件,除非导出

**分隔符包括空格,逗号,制表符(tab),csv是一个逗号分隔的纯文本文件,它的后缀没有意义,也有可能实际上是一个制表符分割的tsv改变文件名而来的,此时用csv打开会报错,该知识点用于防止部分代码中错误应用csv套用tsv等

代码语言:javascript复制
#文件读写部分(文件位于R_02的Rproject中)
#1.读取ex1.txt txt用read.table读,变量名不需要有"",文件名是真实存在的文件,要有""
#直接读取如果失败,需要指定参数
#ex1 <- read.table("ex1.txt") #读入该文件后会发现原文件被认为没有列名,列名被当作第一行,字符型与数值型在一起会将所有数值型改为字符型以满足向量同一类型
ex1 <- read.table("ex1.txt",header = T);ex1 #header=F为默认,如果文件的第一行就是列名,应选用header=T

#2.读取ex2.csv 导入后生成一个数据框
#ex2 <- read.csv("ex2.csv") #读入该文件后会发现原文件第一列被错误当作数据而非行名,且列名的.变成了-,R语言将列名的特殊字符-转化了,该编号可能与其他数据中编号无法匹配,
ex2 <- read.csv("ex2.csv“",row.names = 1,check.names = F) #row.names=1指定第一列为行名,check.names=F指定不转化特殊字符

#注意:数据框不允许重复的行名
#rod = read.csv("rod.csv",row.names = 1) #再次重复:数据框不允许重复的列名,因此报错,显示第一列不符合行名的要求
rod = read.csv("rod.csv")

#3.读取soft.txt
soft <- read.table("soft.txt") #有缺失数据
soft <- read.table("soft.txt",header = T,fill = T) #其实不对,会出现数据的错位
soft2 <- read.table("soft.txt",header = T,sep = "t")
#read.delim也可以读取txt且不容易出现报错

#4.soft 的行数列数与列名
dim(soft)
colnames(soft)

#为了更为方便地处理,可以将不同类型的文件建设文件夹放在Rproject下,读取的时候只需按文件目录的格式输入文件夹名后Tab即可找到
#如a<-read.csv("./name/file"),也可以省略./(相对路径下一级的表示方法,若为../则为上一级)
#文件是由生成它的函数决定的,不是由后缀决定的,save为csv实际上还是一个Rdata
#readr包可以实现base包中的类似功能
library(data.table)
#其中的fread函数可以避免此前的错误
a<-fread("soft.txt",data.table = F)
class(a)
#但其不会有行名,且其会有一个data.table的数据结构多出来,可以设置data.table=F解决
#设置行名如下
rownames(a)<-a[,1]
#import能够更有效地导入且避免一些错误
library(rio)
a=import("exercise.csv",format = "t")
a=import("soft.txt")
#如果导入一个有不同工作簿的xlsx,可以用import_list,此时不同的工作簿作为list里的不同元素
#import高度依赖后缀读写,不能有错
export(a,file="b.xlsx") #也可以按工作簿导出

数据框属性(包括维度、行名、列名)

dim为维度,对数据框使用,输出(行数,列数),nrow输出行数,ncol输出列数

代码语言:javascript复制
dim(df1)
nrow(df1)
ncol(df1)

rowname输出行名,colname输出列名

*注意没有"s",善用Tab可以防止错误

代码语言:javascript复制
rownames(df1)
colnames(df1)

数据框取子集

"$"取子集

df1$gene为对数据框df1列名的向量取子集

*输入df1$后按tab键可以输出待选的列名

mean(df1$score) #对取出的向量可以进行运算

坐标取子集

代码语言:javascript复制
df1[2,2] #取出(行数,列数)的单元格
df1[2,] #取出第二行的所有内容
df1[,2] #取出第二列的所有内容,同df1$
df1[c(1,3),1:2] #取出第1、3行的1、2列数据,取多列的时候需要组织成合适的向量
df1[,-ncol(df1)] #删去最后一列,"-"意义同向量

列名或行名取子集

代码语言:javascript复制
df1[,"gene"] #取出列名为"gene"的单元格
df1[,c('gene','change')] #取出列名为"gene"及"change"的单元格

逻辑值取子集

代码语言:javascript复制
df1[df1$score>0,] #取出列为score的向量中值大于0的数据对应的行
#筛选score > 0的基因
df1[df1$score > 0,1] #df1$score > 0生成一个长度与df对应的逻辑值向量,取出行为TRUE的且列数为1的
df1$gene[df1$score > 0] #先取出列名为gene的向量,在给出一个一一对应的逻辑值向量

数据框修改

修改数据

相当于定位取出数据后赋值,赋值需对应元素或向量

代码语言:javascript复制
df1[3,3] <- 5 #为第3行第3列数据赋值5
df1
df1$score <- c(12,23,50,2)   #为列名为score的列赋值新向量  
df1

新增列

*新增列名与已有的列名不能一样,否则就是修改向量,默认添加到最后

代码语言:javascript复制
df1$p.value <- c(0.01,0.02,0.07,0.05) 
df1

修改行名和列名

代码语言:javascript复制
rownames(df1) <- c("r1","r2","r3","r4") #修改所有行名
colnames(df1)[2] <- "CHANGE" #列出所有行名后取出下标为2的元素赋值修改

数据框的连接

merge函数可连接两个数据框,通过指定公共列使具有相同元素的行的列合并

*merge函数可支持更复杂的连接,但通过inner_join等更为简便,后述

代码语言:javascript复制
test1 <- data.frame(name = c('jimmy','nicker','Damon','Sophie'), 
                    blood_type = c("A","B","O","AB"))
test1
test2 <- data.frame(name = c('Damon','jimmy','nicker','tony'),
                    group = c("group1","group1","group2","group2"),
                    vision = c(4.2,4.3,4.9,4.5))
test2

test3 <- data.frame(NAME = c('Damon','jimmy','nicker','tony'),
                    weight = c(140,145,110,138))
test3
merge(test1,test2,by="name") #两个表格共同的列名是name,只取出列名有交集的
merge(test1,test3,by.x = "name",by.y = "NAME") #test1与test3的共同列列名不一致,需要分别指出作为公共列的列名

也可以借助dplyr包中的函数

代码语言:javascript复制
test1 <- data.frame(name = c('jimmy','nicker','Damon','Sophie'), 
                    blood_type = c("A","B","O","AB"))
test1
test2 <- data.frame(name = c('Damon','jimmy','nicker','tony'),
                    group = c("group1","group1","group2","group2"),
                    vision = c(4.2,4.3,4.9,4.5))
test2
library(dplyr)
inner_join(test1,test2,by="name") #取两者的交集
right_join(test1,test2,by="name") #以右边的为准
full_join(test1,test2,by="name") #两表所有的数据合并
semi_join(test1,test2,by="name") #取左边的右边有的
anti_join(test1,test2,by="name") #取左边的右边没有的

数据框的导出

代码语言:javascript复制
write.csv(soft,file = "soft.csv") #导出数据框为csv的函数,此处soft为变量名,soft.csv应该写全以提示阅读者
write.table(soft,file = "soft.csv") #导出数据框为txt的函数
#最好不要手动修改与直接保存原始文件,可以保证代码的完整性

Rdata的运用

代码语言:javascript复制
#将soft保存为Rdata并加载。
#Rdata是真实存在的文件,保存了数据框、向量、矩阵等变量而不是csv等表格文件
#Rdata只有save与load两个操作,格式如下
save(soft,file = "soft.Rdata")
rm(list = ls())
load(file = "soft.Rdata") #使Rdata中的向量出现在环境内,本身有名称,无需赋值

矩阵和列表

矩阵

矩阵内所有元素数据类型必须相同

*警惕因数据类型不同导致矩阵强制转换引起报错

代码语言:javascript复制
m <- matrix(1:9, nrow = 3) #生成一个向量,并将其分为3行,生成的数据框行名和列名为[1,]等
colnames(m) <- c("a","b","c") #加列名或行名均可以此实现
#取子集方法同数据框
t(m) #转置行与列,数据框转置后为矩阵
as.data.frame(m) #将矩阵转换为数据框

列表

列表内有多个数据框或矩阵,可通过list函数将其组成一个列表

代码语言:javascript复制
l <- list(m1 = matrix(1:9, nrow = 3),m2 = matrix(2:9, nrow = 2));l
l[[2]]  #两个中括号提出第二个组成成分,而l[2]取出来的是一个list,pheatmap不支持
l$m1 #取出名为m1的成分

变量的删除

rm(l) #删除列表l

rm(df1,df2) #删除变量df1与df2

rm(list = ls()) #清空所有变量

附作业答案及解释

代码语言:javascript复制
# 练习3-1
# 1.读取exercise.csv这个文件,赋值给test。
test<-read.csv("exercise.csv")
test
# 2.求test第一列数值的中位数
median(test[,1])
#也可以写成median(test$Petal.Length)
# 3.筛选test中,Species列的值为a或c的行
test[test$Species %in% c("a","c"),]
#注意本题至少有三个问题,第一是值a,c为字符型,要加"",第二是向量是c()不是c<(),第三是中括号内必须标明行与列
#再次注意%in%不会发生循环补齐,因其不是等位运算
# 练习3-2
# 1.统计内置数据iris最后一列有哪几个取值,每个取值重复了多少次
table(iris[,ncol(iris)])
# 2.提取内置数据iris的前5行,前4列,并转换为矩阵,赋值给a。
class(iris)
a<-as.matrix(iris[1:5,1:4]);a
# 3.将a的行名改为flower1,flower2...flower5。
rownames(a)<-paste0("flower",1:5);a
##是rownames不是rowname,可见tab的重要性
#再次说明1:5可以换为1:nrow(a)
# 4.探索列表取子集l[2]和l[[2]]的区别(提示:数据结构)
m<-list(test,test)
class(m[2])
class(m[[2]])

# 练习4-2
# 2、写一个函数,参数是一个数值型向量,输出结果是该向量的平均值加2倍的标准差,并写出用户使用该函数的代码 。
calculate<-function(a){mean(a) 2*sd(a)}
calculate(c(1,1,1))
calculate(rnorm(10,mean=0,sd=1)) #会出现值不相等的情况,此时是因为rnorm()指定的数产生的误差,扩大rnorm取的个数可减少误差

# 安装后加载,library是检验是否安装成功的金标准

#练习5-1:
# 1.读取complete_set.txt(已保存在工作目录)
cs<-read.table("complete_set.txt",header=T)
# 2.查看有多少行、多少列
dim(cs)
# 3.查看列名
colnames(cs)
# 4.导出为csv格式
write.csv(cs,file = "cs.csv")
b=read.csv("cs.csv")
#再次加载会出现第一列莫名其妙的序数,再次加载需要row.name
# 5.保存为Rdata,再加载它
save(cs,file = "cs.Rdata")
# 6.加载y.Rdata(已保存在工作目录),求gene1列的平均值
load(file="y.Rdata")
class(y)
# $不支持矩阵,因此不能在这里使用
class(y[,1])
mean(as.numeric(y[,1]))
#矩阵只允许一种数据类型,单独更改一列的数据类型没有意义,与向量是类似的

0 人点赞