R语言数据结构-数据框&矩阵&列表

R语言数据结构主要有以下四种:

2.数据框

四种数据结构,重点掌握 向量 数据框

Vector向量 :一维,数值型,字符型(加引号),逻辑型。

matrix矩阵:二维,只允许一种数据类型。

data.frame数据框 :二维,每列只允许一种数据类型,列与列之间的数据类型是否相同不管。

list列表:包罗万象,可以包含向量,矩阵,数据框等。

判断数据结构的函数: class()

向量的详细讲解在上一篇文章,以下主要讲数据框,矩阵,列表:

2.数据框

2.1 数据框来源

(1)在R中新建:用代码生成。

(2)由已有数据转换或处理得到:向量组装,矩阵转换,或是从列表里提取。

(3)从文件中读取:把文件导入到R语言里头,一个常规的表格读入到R语言里就是一个数据框。

(4)内置数据集:安装某些R包是自带,有些直接就可以用,如irirs

2.2.1 新建数据框
df <- data.frame(gene    = paste0("gene",1:4),
                 change  = rep(c("up","down"),each = 2),
                 score   = c(5,3,-2,-4))
#    gene change score
# 1 gene1     up     5
# 2 gene2     up     3
# 3 gene3   down    -2
# 4 gene4   down    -4
##有多少个等号就有多少列,多少个变量名(向量)。
##向量的长度(元素个数)决定行数,每个向量的长度要一致。

以下大部分操作使用的数据框为df

2.2.2 从文件中读取数据框
df2 <- read.csv("gene.csv")
#    gene change score
# 1 gene1     up     5
# 2 gene2     up     3
# 3 gene3   down    -2
# 4 gene4   down    -4
##简单的表格读取和赋值
##文件是之前用csv格式保存好,文件一定要放在当前工作目录下,小洁老师帮我们准备好的csv文件

2.2 数据框属性

几个重要的函数:查看数据框的行数和列数,行名和列名;以及单独查行的数量,列的数量

dim()#查数据框几行几列,维度。

rownames(df)#查看行名。

colnames(df)#查看列名。

nrow()#查数据框有几行。

ncol()#查数据框有几列。

df <- data.frame(gene    = paste0("gene",1:4),
                 change  = rep(c("up","down"),each = 2),
                 score   = c(5,3,-2,-4))
##以df数据框演示
dim(df)#查数据框几行几列
#[1] 4 3
##返回数据框的维度,即行数和列数。df数据框4行3列
nrow(df)#数据框有几行
#[1] 4
##统计数据框有几行
ncol(df)#数据框有几列
#[1] 3
##统计数据框有几列
rownames(df)#行名
#[1] "1" "2" "3" "4"
##显示数据框的所有行名
colnames(df)#列名
#[1] "gene"   "change" "score" 
##显示数据框的所有列名

2.3 数据框取子集

数据框取子集有几种方法$符号,坐标,名字,逻辑值

[,]里,行在前面(左边),列在后面(右边),行与列用逗号,隔开:[行,列]

2.3.1 使用$取列
df$score 
##取df数据框的score列
#删掉score,按tab键试试,使用tab键补全,避免拼写错误
mean(df$score)
#[1] 0.5
##求平均值,其实score列就是一个向量,可以进行运算
# 1 gene1     up     5
# 2 gene2     up     3
##对行进行筛选。把df$score>0看做一个整体,返回是一个逻辑值,筛选score列大于0的行。
##细节理解如下:
df$score
#[1]  5  3 -2 -4
df$score > 0
#[1]  TRUE  TRUE FALSE FALSE
df$score[df$score>0]
#[1] 5 3
##df$score看在是一个向量,现在是要把所在的行筛选出来,对数据框而言,行在左边,所以把筛选条件放在行的位置
df[df$score>0,]
#   gene change score
#1 gene1     up     5
#2 gene2     up     3

数据框按照逻辑值取子集,TRUE对应的行/列留下,FALSE对应的行/列去掉。

  • 筛选score对于0的基因:
  • df[df$score>0,1]
    #[1] "gene1" "gene2"
    ##按数据框取子集,要知道基因是在哪一列,在第1列.
    df$gene[df$score>0]
    #[1] "gene1" "gene2"
    ##按照向量取子集,对基因所在的向量操作。
    ##类似y[x>0],x生成的逻辑值给y来用,现在的gene列和score列有对应关系。以前单独向量的y和x没有绑定关系,这是数据框带来隐藏的知识点。
    
  • 变量赋值思维:
  • nn = c('gene','change')
    df[,nn]##相当于代码df[,c('gene','change')],为嵌套代码
    ##用nn替代 c('gene','change'),以后会多次出现时避免写错和冗余,还有以后只在nn = c('gene','change')出修改,联想到ids的赋值。
    ##变量思想,赋值思想
    df[,3]
    #[1]  5  3 -2 -4
    ##取df的第三列
    df[,ncol(df)]
    #[1]  5  3 -2 -4
    ##ncol(df)返回为3,数据框只有3列,其实是取第ncol列,最后一列。
    ##以后联想到删减或是新增一列,关键信息永远都在最后一列ncol(df)。
    df[,-ncol(df)]
    #    gene change
    # 1 gene1     up
    # 2 gene2     up
    # 3 gene3   down
    # 4 gene4   down
    ##-ncol(df)表示不要最后一列。
    ##好奇探索,提取最后一行和去掉最后一行
    df[nrow(df),]
    df[-nrow(df),]
    ##练习题:筛选test中,最后一列(Species)值为a或c的行(没有test数据框没法练习,test由生信技能树提供)
    test2 <- test[test$Species%in%!="b",]
    ##这种做法适合向量里有3选2,如果是50选20比较麻烦
    test2 <- test[test$Species %in% c('a','c'),]
    ##最优的做法,可适用于很多场景。不用==,因为a,c固定等位循环补齐不符合题目要求
    ##小洁老师出的题和答案思路广。
    

    2.4 数据框修改

    2.4.1 改一个格(值)
    df[3,3]<- 5
    ##按坐标修改一个格子,把第三行和第三列的数字改为5
    
    2.4.2 改一整列
    df$score<-c(12,23,50,2)   
    ##修改某一列,一列也是一个向量,修改记得长度一致
    
    2.4.3 增加一列(一般默认放在最后的一列)
    df$p.value <-c(0.01,0.02,0.07,0.05)
    ##增加某一列 
    ##为什么不新增一行,一行里有字符型,数值型,不能以一个向量的形式存在,会把那一行的数值型弄成字符型。
    ##新增一列,因为列与列之间是可以相对独立运行的,数据框所有的操作都是围绕列来操作的。
    ##如果要新增行,把两个类似的表格用rbind()函数拼在一起。
    
    2.4.4 修改行名和列名
    nrow(df)##先看看有几行
    rownames(df) <- c("r1","r2","r3","r4")
    ncol(df)##先看看有几列
    colnames(df) <- c('Gene','differ','point','P')
    ##行名和列名返回是向量,R语言里任何函数的返回结果,要符合R语言内部规则,了解R语言的数据结构和数据类型很重要。修改数据框行名或是列名,相当于对一个向量进行修改就相当于重新赋值。
    
    2.4.5 只修改某一行/列的名
    colnames(df)[2]="CHANGE"
    ##修改第二列的列名,相当于对向量取子集并赋值
    

    修改第二列的列名,就是修改列名这个向量的第二个元素

    2.5 两个数据框的连接

    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
    
  • 两个数据框"列名"不一样的连接:使用merge()函数
  • test1 <- data.frame(name = c('jimmy','nicker','Damon','Sophie'), 
                        blood_type = c("A","B","O","AB"))
    test1
    test3 <- data.frame(NAME = c('Damon','jimmy','nicker','tony'),
                        weight = c(140,145,110,138))
    test3
    ###列名不同的两个数据框第一种连接方式,把一个数据框的列名修改后再连接
    colnames(test3)[1]="name"
    ##列名不同的两个数据框第二种方式:某一列有交集,但是列名不一样的连接 
    merge(test1,test3,by.x = "name",by.y = "NAME")
    ##注意代码里的数据与之对应列名的顺序不能搞错,原来的代码:
    #merge(x=test1,y=test3,by.x = "name",by.y = "NAME")#把最前面的x=和y=省略
    ##要求:共同的一列且要存在交集
    ?merge
    #查看帮助文档
    

    https://blog.csdn.net/weixin_39718006/article/details/110516670

    根据值匹配合并数据框:左连接、右连接、全连接、内连接、半连接、反连接

    left_join(x, y, by)
    right_join(x, y, by)
    full_join(x, y, by)
    inner_join(x, y, by)
    semi_join(x, y, by)
    anti_join(x, y, by)
    

    后续的笔记会有详细介绍

    3.1 矩阵新建和取子集

    3.2.1 新建矩阵
    m <- matrix(1:9, nrow = 3)
    ##1:9,1到9个数字,排成3行。参数nrow=3 或是 ncol=3都可以
    #       [,1] [,2] [,3]
    # [1,]    1    4    7
    # [2,]    2    5    8
    # [3,]    3    6    9
    ##没有行名和列名的矩阵
    
    3.2.2 矩阵取子集:[ ]

    矩阵不能用$符号取子集

    m[2,]
    m[,1]
    m[2,3]
    m[2:3,1:2]
    

    3.2 矩阵的转置和转换

    t():转置函数,行与列的互换

    as.data.frame():转换,把矩阵变为数据框,用as.matrix()函数也能把数据框变为矩阵

    colnames(m) <- c("a","b","c") 
    #行变列,列变行,t()转置函数
    as.data.frame(m)
    ##把m矩阵转换为数据框
    class(m)
    ##仍旧是矩阵,要赋值才真正发生保存的变化,df=as.data.frame(m)
    as.matrix(df)
    ##把数据框df转换为矩阵
    ##as开头表示转换
    

    3.3 矩阵画热图

    # a b c # [1,] 1 4 7 # [2,] 2 5 8 # [3,] 3 6 9 pheatmap::pheatmap(m)

    聚类,相似的行,相似的列会聚在一起。热图自动聚类,行和列的相对位置发生了变化,只是列与列,行与行之间的变化规律。

    ![热图自动聚类]](https://upload-images.jianshu.io/upload_images/17511166-f6e2432a04cffbbe.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    热图默认聚类,修改参数,不让聚类,热图与表达矩阵对应。

    pheatmap::pheatmap(m,cluster_rows = F,cluster_cols =F )
    ##热图默认为T,行聚类,列聚类,改为F就不聚类,使用tab键补全,参数不需要手打字。
    

    $有两个作用:数据框取子集和列表取子集。在矩阵和向量里不能用$

    class()函数更能具体说明问题,判断数据结构和数据类型

    df <- data.frame(gene    = paste0("gene",1:4),
                     change  = rep(c("up","down"),each = 2),
                     score   = c(5,3,-2,-4))
     class(df)
    #[1] "data.frame"
    class(df$gene)
    #[1] "character"
    class(df$score)
    #[1] "numeric"
    class(df$change)
    #[1] "character"
    

    5.补充知识

    5.1元素的"名字" -names()
    scores = c(100,59,73,95,45)
    names(scores) = c("jimmy","nicker","Damon","Sophie","tony")
    scores
    # jimmy nicker  Damon Sophie   tony 
    # 100     59     73     95     45 
    ##在一种简单的数据结构里容纳两种不同的信息,好处在向量里容纳不同的两种信息,但是名字仅仅是向量的一个属性,就是说,不会因为向量拥有名字而改变它本身是数值型向量的事实,有无名字都不会改变该向量为数值型向量。名字的用处是用于提子集,如下:
    scores["jimmy"]
    # jimmy 
    # 100 
    ##提取单个元素的分数,等同于代码:scores[1]
    scores[c("jimmy","nicker")]
    # jimmy nicker 
    # 100     59 
    ##提取多个元素的分数,用c()函数,等同于代码:scores[c(1,2)]
    names(scores)[scores>60]
    #[1] "jimmy"  "Damon"  "Sophie"
    ##以后应用在提取表达量大于多少的基因
    scores[scores>60]
    # jimmy  Damon Sophie 
    # 100     73     95 
    

    5.2 删除变量
    ##每次赋值后环境里都会多一个变量,引进后再推出去,即删除。
    rm(l)
    ##删除一个变量。
    rm(df,m)
    ##删除多个
    rm(list = ls()) 
    ##删除全部,常用,每次在分析数据(或是调试代码)第一句都会是这句代码。清空环境,后面实战反复出现。
    control l
    ##按control 和 l键,清空控制台。