R 语言编程— 基于tidyverse读书笔记(20220906)

注:根据张敬信老师的《R语言编程—基于tidyverse》一书,所作笔记。

第一章 基础语法

本章将学习R 语言基本语法,也是与其他编程语言相通的部分,包括:搭建R 环境、常用数据类型(数据结构)、控制结构(分支、循环)、自定义函数。

1.1 搭建R 环境及常用操作

1.1.1 搭建R 环境

  1. 安装R
    从R语言的官网The R Project for Statistical Computing下载R安装包,根据自己的操作系统,下载相应的最新版安装即可。linux推荐conda安装,可以管理不同的R版本,更好处理依赖关系。
  2. 安装RStudio
    从RStudio官网下载安装RStudio: 桌面版服务器版

1.1.2 常用操作

  1. 安装包
    扩展包(package),简称包。通常R 包都来自CRAN,审核比较规范严格,包的质量相对更有保障。建议使用命令安装:
    install.packages("openxlsx")
    Github 也是R 包的较大的来源,有些作者自己开发的R 包只放在Github,也有很多CRAN R 包的最新开发版都位于Github. 可以先安装devtools 或remotes 包,再用其install_github() 安装Github 来源的包:
    devtools::install_github("tidyverse/dplyr") # 或者
    remotes::install_github("tidyverse/dplyr")
    若网络等原因,导致直接从Github 安装包失败,也可以将整个包文件夹从网页下载下来,解压缩到当前路径(或提供完整路径),再从本地安装它:
    install.packages("dplyr-master", repos=NULL, type="source")
    另外,生信领域在R 中自成一派,有专门的包的大本营:bioconductor,先安装BiocManager 包,再用install() 函数安装bioconductor 来源的包:
    BiocManager::install("openxlsx")
  2. 加载包
    library(openxlsx)
  3. 更新包
    update.packages("openxlsx")
    update.packages() # 更新所有包
  4. 删除包
    remove.packages("openxlsx")
  5. 获取或设置当前路径
    getwd()
    setwd("D:/R-4.1.1/tests")
  6. 赋值
    R 标准语法中赋值不是用= ,而是<- 或->
    x <- 1:10
    x + 2
    #[1] 3 4 5 6 7 8 9 10 11 12
    R 也允许用= 赋值,建议用更现代和简洁的= 赋值。
  7. 基本运算
    数学运算:
    + - * /、^ (求幂) 、%% (按模求余1) 、%/% (整除)
    比较运算:
    >、<、>=、<=、==、!=
    identical(x,y)—— 判断两个对象是否严格相等;
    all.equal(x,y) 或dplyr::near(x,y)——判断两个浮点数是否近似相等(误差1.5e−8)
0L == 0
## [1] TRUE
identical(0L, 0)
## [1] FALSE
sqrt(2)^2 == 2
## [1] FALSE
identical(sqrt(2)^2, 2)
## [1] FALSE
all.equal(sqrt(2)^2, 2)
## [1] TRUE
dplyr::near(sqrt(2)^2, 2)
## [1] TRUE

逻辑运算:
| (或) , & (与) ,! (非) ,xor() (异或)

&& 和|| 是短路运算,即遇到TRUE (FALSE) 则返回TRUE (FALSE) 而不继续往下计算;而& 和| 是向量运算符,对向量中所有元素分别进行运算。

  1. 基本数据类型
    R 中的基本数据类型包括:
    numeric——数值型,又分为integer (整数型) 和double (浮点型)
    logical——逻辑型,只有TRUE 和FALSE,或T 和F
    character——字符型,引号括起来的若干字符

R 中用NA 表示缺失值,NULL 表示空值,NaN 表示非数,Inf 表示无穷大
对于R 中大多数函数,NA 具有传染性,即NA 参与的运算,结果会变成NA
R 中注释一行代码用#
可用函数class(x) / typeof(x) / mode(x) 查看对象x 的类型
在展现数据的细节上,mode() < class() < typeof()
str(x) 显示对象x 的结构

  1. 保存和载入数据
    save(x, file = "datas/dat.Rda")
    load("datas/dat.Rda")
  2. 清屏和清除内存变量
    Ctrl + L 或单击命令窗口右上角的小刷子可对命令窗口清屏。
    若要清除当前变量,用:
    rm(x) # 清除变量x
    rm(list = ls(all = TRUE)) # 清除所有当前变量
    注:单击Environment 窗口的小刷子也是清除所有当前变量。
  3. 获取帮助
    编程语言最好的学习资料就是帮助。
    函数帮助
    命令窗口执行:?plot
    ?plot
  4. R Script 与R Project
    R 脚本是单个可执行的R 代码文件,后缀名为.R,单击New File 按钮,选择R Script,或使用快捷键Ctrl + Shift + N, 则新建R 脚本。
    R 脚本中都是可执行的R 代码+ 注释,选中部分代码,点击Run 运行选中的代码。
    R 项目(Project)是完成某个项目或任务的一系列文件的合集(文件夹) ,包括数据文件、若干R脚本及其他附件,其中包含一个*.Rproj 文件;
    强烈建议使用R 项目,它能方便系统地管理服务于共同目的一系列的文件,可以方便移动位置甚至是移到其他电脑,而不需要做任何路径设置就能成功运行。
  5. Rmarkdown
    后缀名为.Rmd 的交互式文档,是markdown 语法与R 脚本的结合,可以将可执行R 代码和不可执行的文字叙述,融为一个文件。

1.2 数据结构I:向量、矩阵、多维数组

数据结构是为了便于存储不同类型的数据而设计的数据容器。
R 中常用的数据结构可划分为:
同质数据类型(homogeneous) ,即所存储的一定是相同类型的元素,包括向量、矩阵、多维数组;
异质数据类型(heterogeneous) ,即可以存储不同类型的元素,这大大提高了存储的灵活性,但同时也降低了存储效率和运行效率,包括列表、数据框。
另外,还有字符串、日期时间数据、时间序列数据、空间地理数据等。
向量都有两个属性:type (类型) 、length (长度) ;还能以属性的方式向向量中任意添加额外的metadata (元数据) ,属性可用来创建扩展向量,以执行一些新的操作。常用的扩展向量有:

  • 基于整数型向量构建的因子
  • 基于数值型向量构建的日期和日期时间
  • 基于数值型向量构建的时间序列
  • 基于列表构建的数据框和tibble

1.2.1 向量(一维数据)

向量是由一组相同类型的原始值构成的序列,可以是一组数值、一组逻辑值、一组字符串等。
常用的向量有:数值向量、逻辑向量、字符向量。

  1. 数值向量
    数值向量就是由数值组成的向量,单个数值是长度为1 的数值向量
x = 1.5
x
## [1] 1.5

可以用numeric() 来创建一个全为0 的指定长度的数值向量:

numeric(10)
## [1] 0 0 0 0 0 0 0 0 0 0

R 中经常用函数c() 实现将多个对象合并到一起:

c(1, 2, 3, 4, 5)
## [1] 1 2 3 4 5
c(1, 2, c(3, 4, 5)) # 将多个数值向量合并成一个数值向量
## [1] 1 2 3 4 5

创建等差的数值向量,用: 或者函数seq() ,基本格式为:
seq(from, to, by, length.out, along.with, ...)
from:设置首项(默认为1) ;
to:设置尾项;
by:设置等差值(默认为1 或-1) ;
length.out:设置序列长度;
along.with:以该参数的长度作为序列长度。

1:5 # 同seq(5) 或seq(1,5)
## [1] 1 2 3 4 5
seq(1, 10, 2) # 从1 开始, 到10 结束, 步长为2
## [1] 1 3 5 7 9
seq(3, length.out=10)
## [1] 3 4 5 6 7 8 9 10 11 12

创建重复的数值向量用函数rep(),基本格式为:
rep(x, times,length.out, each, ...)
x:为要重复的序列;
times:设置序列重复次数;
length.out:设置产生的序列的长度;
each:设置每个元素分别重复的次数(默认为1) 。

x = 1:3
rep(x, 2)
## [1] 1 2 3 1 2 3
rep(x, each = 2)
## [1] 1 1 2 2 3 3
rep(x, c(2, 1, 2)) # 按照规则重复序列中的各元素
## [1] 1 1 2 3 3
rep(x, each = 2, length.out = 4)
## [1] 1 1 2 2
rep(x, each = 2, times = 3)
## [1] 1 1 2 2 3 3 1 1 2 2 3 3 1 1 2 2 3 3
  1. 逻辑向量
    逻辑向量,是一组逻辑值(TRUE 或FALSE, 或简写为T 或F) 的向量。
c(1, 2) > c(2, 1) # 等价于c(1 > 2, 2 > 1)
## [1] FALSE TRUE
c(2, 3) > c(1, 2, -1, 3) # 等价于c(2 > 1, 3 > 2, 2 > -1, 3 > 3)
## [1] TRUE TRUE TRUE FALSE
除了比较运算符外,还可以用%in% 判断元素是否属于集合:
c(1, 4) %in% c(1, 2, 3) # 左边向量每一个元素是否属于右边集合
## [1] TRUE FALSE
  1. 字符向量
    字符(串) 向量,是一组字符串组成的向量,R 中单引号和双引号都可以用来生成字符向量。
"hello, world!"
## [1] "hello, world!"
c("Hello", "World")
## [1] "Hello" "World"
c("Hello", "World") == "Hello, World"
## [1] FALSE FALSE
  1. 访问向量子集
    即访问向量的一些特定元素或者某个子集。注意,R 中的索引是从1 开始的。
    使用元素的位置来访问:
v1 = c(1, 2, 3, 4)
v1[2] # 第2 个元素
v1[2:4] # 第2-4 个元素
v1[-3] # 除了第3 个之外的元素

也可以放任意位置的数值向量,但是注意不能既放正数又放负数:

v1[c(1,3)]
v1[c(1, 2, -3)] # 报错

访问不存在的位置也是可以的,返回NA:

v1[3:6]

使用逻辑向量来访问,输入与向量相同长度的逻辑向量,以此决定每一个元素是否要被获取:

v1[c(TRUE, FALSE, TRUE, FALSE)]

这可以引申为‘‘根据条件访问向量子集’’:

v1[v1 <= 2] # 同v1[which(v1 <= 2)] 或subset(v1, v1<=2)
v1[v1 ^ 2 - v1 >= 2]
which.max(v1) # 返回向量v1 中最大值所在的位置
which.min(v1) # 返回向量v1 中最小值所在的位置
  1. 对向量子集赋值,替换相应元素
    对向量子集赋值,就是先访问到向量子集,再赋值。
v1[2] = 0
v1[2:4] = c(0, 1, 3)
v1[c(TRUE, FALSE, TRUE, FALSE)] = c(3, 2)
v1[v1 <= 2] = 0

注意,若对不存在的位置赋值,前面将用NA 补齐。

  1. 对向量元素命名
    可以在创建向量的同时对其每个元素命名:
x = c(a = 1, b = 2, c = 3)
x
## a b c
## 1 2 3

命名后,就可以通过名字来访问向量元素:

x[c("a", "c")]
x[c("a", "a", "c")] # 重复访问也是可以的
x["d"] # 访问不存在的名字

获取向量元素的名字:

names(x)
## [1] "a" "b" "c"

更改向量元素的名字:

names(x) = c("x", "y", "z")
x["z"]
## z
## 3

移除向量元素的名字:

names(x) = NULL
x
## [1] 1 2 3
  1. 对向量排序

向量排序函数sort(),基本格式为:
sort(x, decreasing, na.last, ...)
x:为排序对象(数值型或字符型) ;
decreasing:默认为FALSE 即升序,TRUE 为降序;
na.last:默认为FALSE,若为TRUE,则将向量中的NA 值放到序列末尾。
函数order(), 返回元素排好序的索引,以其结果作为索引访问元素,正好是排好序的向量。
函数rank(),返回值是该向量中对应元素的‘‘排名’’。

x = c(1,5,8,2,9,7,4)
sort(x)
## [1] 1 2 4 5 7 8 9
order(x) # 默认升序,排名第2 的元素在原向量的第4 个位置
## [1] 1 4 7 2 6 3 5
x[order(x)] # 同sort(x)
## [1] 1 2 4 5 7 8 9
rank(x) # 默认升序,第2 个元素排名第4 位
## [1] 1 4 6 2 7 5 3

1.2.2 矩阵(二维数据)

矩阵是一个用两个维度表示和访问的向量。因此,适用于向量的性质和方法大多也适用于矩阵:矩阵也要求元素是同一类型,数值矩阵、逻辑矩阵等。

  1. 创建矩阵

函数matrix() 将一个向量创建为矩阵,其基本格式为:
matrix(x, nrow, ncol, byrow, dimnames, ...)
x:为数据向量作为矩阵的元素;
nrow:设定行数;
ncol:设定列数;
byrow:设置是否按行填充,默认为FALSE (按列填充) ;
dimnames:用字符型向量表示矩阵的行名和列名。

matrix(c(1, 2, 3,
4, 5, 6,
7, 8, 9), nrow = 3, byrow = FALSE)
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
matrix(c(1, 2, 3,
4, 5, 6,
7, 8, 9), nrow = 3, byrow = TRUE)
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
## [3,] 7 8 9
#对矩阵的行列命名:
matrix(1:9, nrow = 3, byrow = TRUE,
dimnames = list(c("r1","r2","r3"), c("c1","c2","c3")))
## c1 c2 c3
## r1 1 2 3
## r2 4 5 6
## r3 7 8 9
#也可以创建后再命名:
m1 = matrix(c(1, 2, 3, 4, 5, 6, 7, 8, 9), ncol = 3)
rownames(m1) = c("r1", "r2", "r3")
colnames(m1) = c("c1", "c2", "c3")
  1. 访问矩阵子集
    矩阵是用两个维度表示和访问的向量,可以用一个二维存取器[ , ] 来访问,这类似于构建向量子集时用的一维存取器[]。可以为每个维度提供一个向量来确定一个矩阵的子集。方括号中的第1 个参数是行选择器,第2个参数是列选择器。与构建向量子集一样,可以在两个维度中使用数值向量、逻辑向量和字符向量。
m1[1,2] # 提取第1 行,第2 列的单个元素
m1[1:2, 2:4] # 提取第1 至2 行,第2 至4 列的元素
m1[c("r1","r3"), c("c1","c3")] # 提取行名为r1 和r3,列名为c1 和c3 的元素
若一个维度空缺,则选出该维度的所有元素:
m1[1,] # 提取第1 行,所有列元素
m1[,2:4] # 提取所有行,第2 至4 列的元素
负数表示在构建矩阵子集时可排除该位置,这和向量中的用法一致:
m1[-1,] # 提取除了第1 行之外的所有元素
m1[,-c(2,4)] # 提取除了第2 和4 列之外的所有元素

注意,矩阵是一个用两个维度表示和访问的向量,但它本质上仍然是一个向量。因此,向量的一
维存取器也可以用来构建矩阵子集:

m1[3:7]
## [1] 3 4 5 6 7
由于向量只包含相同类型的元素,矩阵也是如此。所以它们的操作方式也相似。若输入一个不等
式,则返回同样大小的逻辑矩阵:
m1 > 3
## c1 c2 c3
## r1 FALSE TRUE TRUE
## r2 FALSE TRUE TRUE
## r3 FALSE TRUE TRUE
根据它就可以选择矩阵元素或赋值:
m1[m1 > 3] # 注意选出来的结果是向量
## [1] 4 5 6 7 8 9

1.2.3 多维数组(多维数据)

向量/矩阵向更高维度的自然推广。具体来说,多维数组就是一个维度更高(通常大于2) 、可访问的向量。数组也要求元素是同一类型。

  1. 创建多维数组

函数array() 将一个向量创建为多维数组,基本格式为:
array(x, dim, dimnames, ...)
x:为数据向量作为多维数组的元素;
dim:设置多维数组各维度的维数;
dimnames:设置多维数组各维度的名称。

a1 = array(1:24, dim = c(3, 4, 2))
a1
## , , 1
##
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
##
## , , 2
##
## [,1] [,2] [,3] [,4]
## [1,] 13 16 19 22
## [2,] 14 17 20 23
## [3,] 15 18 21 24
也可以在创建数组时对每个维度进行命名:
a1 = array(1:24, dim = c(3, 4, 2),dimnames=list(c("r1","r2","r3"),c("c1","c2","c3","c4"), c("k1","k2")))
或者创建之后再命名
a1 = array(1:24, dim = c(3, 4, 2))
dimnames(a1) = list(c("r1","r2","r3"),c("c1","c2","c3","c4"), c("k1","k2"))
  1. 访问多维数组子集
    第3 个维度姑且称为‘‘页”
a1[2,4,2] # 提取第2 行, 第4 列, 第2 页的元素
a1["r2","c4","k2"] # 提取第r2 行, 第c4 列, 第k2 页的元素
a1[1,2:4,1:2] # 提取第1 行, 第2 至4 列, 第1 至2 页的元素
a1[,,2] # 提取第2 页的所有元素
dim(a1) # 返回多维数组a1 的各维度的维数

1.3 数据结构II:列表、数据框、因子

1.3.1 列表(list)

列表,可以包含不同类型的对象,甚至可以包括其他列表。列表最大的好处就是,它能够将多个不同类型的对象打包到一起,使得可以根据位置和名字访问它们。

  1. 创建列表
    可以用函数list() 创建列表。不同类型的对象可以放入同一个列表中。
l0 = list(1, c(TRUE, FALSE), c("a", "b", "c"))
l0
## [[1]]
## [1] 1
##
## [[2]]
## [1] TRUE FALSE
##
## [[3]]
## [1] "a" "b" "c"
可以在创建列表时,为列表的每个成分指定名字:
l1 = list(A = 1, B = c(TRUE, FALSE), C = c("a", "b", "c"))
l1
## $A
## [1] 1
##
## $B
## [1] TRUE FALSE
##
## $C
## [1] "a" "b" "c"
也可以创建列表后再对列表成分命名或修改名字:
names(l1) = NULL # 移除列表成分的名字
names(l1) = c("x","y","z")
  1. 从列表中提取成分的内容
    提取列表中成分下的内容,最常用的方法是用$,通过成分名字来提取该成分下的内容:
l1$y
l1$m # 访问不存在的成分m, 将会返回NULL
也可以用[[n]] 来提取列表第n 个成分的内容,n 也可以换成成分的名字:
l1[[2]] # 同l1[["y"]]
用[[]] 提取列表中某个成分的内容更加灵活,可用在函数调用中,通过参数来传递成分名字:
p = "y" # 想要提取其内容的成分名字
l1[[p]]
  1. 提取列表子集
    经常也需要从列表中提取多个成分及其内容,由这些成分组成的列表构成了原列表的一个子集。就像提取向量和矩阵的子集一样,提取一个列表子集是用[],可以取出列表中的一些成分,作为一个新的列表。[] 中可以用字符向量表示成分名字,用数值向量表示成分位置,或用逻辑向量指定是否选择,来取出列表成分。
l1["x"] # 同l1[1]
l1[c("x", "z")] # 同l1[c(1, 3)], l1[c(TRUE, FALSE, TRUE)]

用[] 提取若干成分时,返回列表的子集,还是一个列表;用[[ ]] 提取单个成分的元素,返回的是对应成分的元素。总之,[] 提取对象的子集,类型仍是该对象;[[]] 提取对象的内容(下一级元素) 。

  1. 对列表的成分赋值
    即先访问(提取) 到列表的成分,再赋以相应的值。注意,若给一个不存在的成分赋值,列表会自动地在对应名称或位置下增加一个新成分。
l1$x = 0 # 将列表的成分x 赋值为0
也可以同时给多个列表成分赋值:
l1[c("x", "y")] = list(x = "new value for y", y = c(3, 1))
若要移除列表中的某些成分,只需赋值为NULL:
l1[c("z", "m")] = NULL
  1. 列表函数
    用函数as.list() 可将向量转换成列表:
l2 = as.list(c(a = 1, b = 2))
l2
## $a
## [1] 1
##
## $b
## [1] 2
用去列表化函数unlist(),可将一个列表打破成分界线,强制转换成一个向量:
unlist(l2)
## a b
## 1 2

tidyverse 系列中的purrr 包为方便操作列表,提供了一系列列表相关的函数,建议读者查阅使
用:
pluck():同[[ 提取列表中的元素
keep(): 保留满足条件的元素
discard(): 删除满足条件的元素
compact(): 删除列表中的空元素
append():在列表末尾增加元素
flatten(): 摊平列表(只摊平一层)

1.3.2 数据框(数据表)

数据框是由列向量组成、有着矩阵形式的列表。数据框与最常见的数据表是一致的:每一列代表一个变量属性,每一行代表一条样本数据。R 中自带的数据框是data.frame,建议改用更现代的数据框:tibble。

  1. 创建数据框
    用tibble() 根据若干列向量创建tibble:
library(tidyverse) # 或tibble
persons = tibble(
Name = c("Ken", "Ashley", "Jennifer"),
Gender = c("Male", "Female", "Female"),
Age = c(24, 25, 23),
Major = c("Finance", "Statistics", "Computer Science"))
persons
## # A tibble: 3 x 4
## Name Gender Age Major
## <chr> <chr> <dbl> <chr>
## 1 Ken Male 24 Finance
## 2 Ashley Female 25 Statistics
## 3 Jennifer Female 23 Computer Science
用tribble() 按行录入数据式创建tibble:
tribble(
~Name, ~Gender, ~Age, ~Major,
"Ken", "Male", 24, "Finance",
"Ashley", "Female", 25, "Statistics",
"Jennifer", "Female", 23, "Computer Science")
用as_tibble() 将data.frame, matrix, 各成分等长度的list, 转换为tibble。
对于不等长的列表转化为数据框:
a = list(A = c(1, 3, 4), B = letters[1:4])
a
## $A
## [1] 1 3 4
##
## $B
## [1] "a" "b" "c" "d"
# lengths() 获取list 中每个元的长度
map_dfc(a, `length<-`, max(lengths(a))) # map 循环参阅1.6.2 节
## # A tibble: 4 x 2
## A B
## <dbl> <chr>
## 1 1 a
## 2 3 b
## 3 4 c
## 4 NA d
df = tibble(id = 1:4,
level = c(0, 2, 1, -1),
score = c(0.5, 0.2, 0.1, 0.5))
names(df) = c("id", "x", "y")
df
## # A tibble: 4 x 3
## id x y
## <int> <dbl> <dbl>
## 1 1 0 0.5
## 2 2 2 0.2
## 3 3 1 0.1
## 4 4 -1 0.5

数据框既是列表的特例,也是矩阵的推广,因此访问这两类对象的方式都适用于数据框。

  1. 提取数据框的元素、子集
    (1) 以列表方式提取数据框的元素、子集
    可以用$ 按列名来提取某一列的值,或者用[[]] 按照位置或列名提取。例如,提取列名为x 列的值,得到向量:
df$x # 同df[["x"]], df[[2]]
## [1] 0 2 1 -1

以列表形式构建子集完全适用于数据框,同时也会生成一个新的数据框。提取子集的操作符[] 允许用数值向量表示列的位置,用字符向量表示列名,或用逻辑向量指定是否选择。

例如,提取数据框的一列或多列,得到子数据框:

df[1] # 提取第1 列, 同df["id"]
## # A tibble: 4 x 1
## id
## <int>
## 1 1
## 2 2
## 3 3
## 4 4
df[1:2] # 同df[c("id","x")], df[c(TRUE,TRUE,FALSE)]
## # A tibble: 4 x 2
## id x
## <int> <dbl>
## 1 1 0
## 2 2 2
## 3 3 1
## 4 4 -1

(2) 以矩阵方式提取数据框的元素、子集
以列表形式操作并不支持行选择。以矩阵形式操作更加灵活,若将数据框看作矩阵,其二维形式 的存取器可以很容易地获取一个子集的元素,同时支持列选择和行选择。换句话说,可以使用[i, j] 指定行或列来提取数据框子集,[ , ] 内可以是数值向量、字符向量或者逻辑向量。

若行选择器为空,则只选择列(所有行) :
df[, "x"]
## # A tibble: 4 x 1
## x
## <dbl>
## 1 0
## 2 2
## 3 1
## 4 -1
df[, c("x","y")] # 同df[,2:3]
## # A tibble: 4 x 2
## x y
## <dbl> <dbl>
## 1 0 0.5
## 2 2 0.2
## 3 1 0.1
## 4 -1 0.5
若列选择器为空,则只选择行(所有列) :
df[c(1,3),]
## # A tibble: 2 x 3
## id x y
## <int> <dbl> <dbl>
## 1 1 0 0.5
## 2 3 1 0.1
同时选择行和列:
df[1:3, c("id","y")]
## # A tibble: 3 x 2
## id y
## <int> <dbl>
## 1 1 0.5
## 2 2 0.2
## 3 3 0.1

根据条件筛选数据。例如用y >= 0.5 筛选df 的行,并选择id 和y 两列:

df[df$y >= 0.5, c("id","y")]
## # A tibble: 2 x 2
## id y
## <int> <dbl>
## 1 1 0.5
## 2 4 0.5

按列名属于集合{x, y, w} 来筛选df 的列,并选择前两行:

ind = names(df) %in% c("x","y","w")
df[1:2, ind]
## # A tibble: 2 x 2
## x y
## <dbl> <dbl>
## 1 0 0.5
## 2 2 0.2
  1. 给数据框赋值
    给数据框赋值,就是选择要赋值的位置,再准备好同样大小且格式匹配的数据,赋值给那些位置即可,所以同样有列表方式和矩阵方式。
    (1) 以列表方式给数据框赋值
用$ 或[[ ]] 对数据框的1 列赋值
df$y = c(0.6,0.3,0.2,0.4) # 同df[["y"]] = c(0.6,0.3,0.2,0.4)
利用现有列,创建(计算) 新列:
df$z = df$x + df$y
df
## # A tibble: 4 x 4
## id x y z
## <int> <dbl> <dbl> <dbl>
## 1 1 0 0.5 0.5
## 2 2 2 0.2 2.2
## 3 3 1 0.1 1.1
## 4 4 -1 0.5 -0.5
df$z = as.character(df$z) # 转换列的类型
df
## # A tibble: 4 x 4
## id x y z
## <int> <dbl> <dbl> <chr>
## 1 1 0 0.5 0.5
## 2 2 2 0.2 2.2
## 3 3 1 0.1 1.1
## 4 4 -1 0.5 -0.5
用[] 可以对数据框的1 列或多列进行赋值:
df["y"] = c(0.8,0.5,0.2,0.4)
df[c("x", "y")] = list(level = c(1,2,1,0),
score = c(0.1,0.2,0.3,0.4))

(2) 以矩阵方式给数据框赋值
以列表方式对数据框进行赋值时,也是只能访问列。若需要更加灵活地进行赋值操作,可以以矩阵方式进行。

df[1:3,"y"] = c(-1,0,1)
df[1:2,c("x","y")] = list(level = c(0,0),score = c(0.9,1.0))
  1. 一些有用函数

函数str() 或glimpse() 作用在R 对象上,显示该对象的结构:

str(persons)
## tibble [3 x 4] (S3: tbl_df/tbl/data.frame)
## $ Name : chr [1:3] "Ken" "Ashley" "Jennifer"
## $ Gender: chr [1:3] "Male" "Female" "Female"
## $ Age : num [1:3] 24 25 23
## $ Major : chr [1:3] "Finance" "Statistics" "Computer Science"

summary() 作用在数据框/列表上,将生成各列/成分的汇总信息:

summary(persons)
## Name Gender Age
## Length:3 Length:3 Min. :23.0
## Class :character Class :character 1st Qu.:23.5
## Mode :character Mode :character Median :24.0
## Mean :24.0
## 3rd Qu.:24.5
## Max. :25.0
## Major
## Length:3
## Class :character
## Mode :character

经常需要将多个数据框(或矩阵) 按行或按列进行合并。用函数rbind(),增加行(样本数据) ,要求宽度(列数) 相同;用函数cbind(),增加列(属性变量) ,要求高度(行数) 相同。

例如,向数据框persons 数据框中添加一个人的新记录:


rbind(persons,
tibble(Name = "John", Gender = "Male",
Age = 25, Major = "Statistics"))
## # A tibble: 4 x 4
## Name Gender Age Major
## <chr> <chr> <dbl> <chr>
## 1 Ken Male 24 Finance
## 2 Ashley Female 25 Statistics
## 3 Jennifer Female 23 Computer Science
## 4 John Male 25 Statistics

向persons 数据框中添加两个新列表示每个人是否已注册和其手头的项目数量:

cbind(persons, Registered = c(TRUE, TRUE, FALSE),
Projects = c(3, 2, 3))
## Name Gender Age Major Registered Projects
## 1 Ken Male 24 Finance TRUE 3
## 2 Ashley Female 25 Statistics TRUE 2
## 3 Jennifer Female 23 Computer Science FALSE 3

rbind() 和cbind() 不会修改原始数据,而是生成一个添加了行或列的新数据框。

函数expand.grid() 可生成多个属性水平值所有组合(笛卡儿积) 的数据框:

expand.grid(type = c("A","B"), class = c("M","L","XL"))
## type class
## 1 A M
## 2 B M
## 3 A L
## 4 B L
## 5 A XL
## 6 B XL
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容