1.R语言基础知识-程序员宅基地

技术标签: r语言  R语言  临床统计分析  

目录

一、R语言的介绍

R语言的下载与按照

Rstudio

R包的安装

工作空间管理

基本运算

二、R的数据结构

1. 数据类型

2. 数据类型的转换和判断

3.数据结构

三、导入/导出数据

获取内置数据集

获取其他格式的数据

四、数据框的常用操作

1.处理数据框的基本函数

2. 筛选行和列

3. arrange()排列行

4.添加新的变量

5. 拆分数据框

6. 数据框的合并

7. %>%的传递操作

8. 数据框长宽格式转换

9. 缺失值处理

10. 条件循环语句

11. 分割列数据和合并列数据

12. 字符串常用函数

13. 大型数据集的处理策略


一、R语言的介绍

R语言的下载与按照

R语言的下载网址:R: The R Project for Statistical Computing

建议下载最新版本,避免有些R包无法运行。 此外选择镜像下载,下载速度会快很多。

 国内的镜像比较多,所以可以根据自己的所在位置选择合适的镜像。因为笔者在北京,就选择了北大镜像下载。安装的话建议直接默认,点击下一步,装在C盘的位置。

Rstudio

Rstudio下载网站:Posit | The Open-Source Data Science Company

Rstudio界面介绍:

 1.脚本编辑器:这个区域主要是用来撰写代码,编辑器写的代码不会直接执行,并且可以保存成为.R格式的文件,保存既往的代码。可以直接打开,修改,运行。

2.控制台:是R的运算执行区域,可以直接写代码,但是由于不利于保存,较少在控制台写代码。二、控制台还可以显示运算的结果。

3.环境:该区域主要是存储目前的数据内容,包括任何数据格式

4.其他菜单栏:file默认是当前的工作路径,plot输出的图片结果展示,package是R中已经安装的R包。

R包的安装

R包:可以理解成为多个函数的打包存放,包含函数、数据、帮助文档、描述文档等

R包分为3类:1.基础包,在R启动的时候自动调入内存,以满足基础的数据处理和统计分析需要。2.备用包,随着R安装而安装,但是需要使用函数library()或require()调入内存后才能使用。3.捐赠包,由统计专家发布,用户需要单独下载,然后用函数library()或require()调入内存后才能使用。

1. 查看当前内存中调用的R包。

search() #目前工作状态下有哪些R包被加载
require("strings")#strings包是否安装,输出为逻辑值T或者F

2. R包的安装

包使用的顺序:安装——加载——调用函数

R包是否安装成功评价:library加载时是否会报错

方法一:install.packages("R包名称" )

install.packages("epiDisplay")
install.packages("BiocManager")

上面的命令安装了名为“epiDisplay”的包,凡是CRAN的R包,都统一使用install.package()

方法二:bioconductor中的R包,统一使用BiocManager::install()安装

BiocManager::install("limma")

因为在安装limma包时会同时安装一些其他包,如果这些包某些已经被安装,则会提示是否更新这些包?一般情况选择none,只需要在控制台回复n。

 方法三:github上的R包,使用devtools::install_github()

install.packages("devtools")#第一次需要先安装devtools包
devtools::install_github("jmzeng1314/idmap1")

发布在github上的包,需要在包的名字前面包含作者名字。

已经安装的包,可以用::快速调用里面的函数

!!!!!更新R包,重新安装,先删除后重新安装。建议不用update()

常见的报错:

  • 关键词connection,internet,url、404、http,download往往是网络限制,或者镜像没有选择合适
  • not writable/permission denied 权限问题:管理员方式重新打开Rstudio,重新安装
  • ????中文用户名惹的祸,修改环境变量
  • package not available 四种问题:1.包的名字拼写错误;2.命令用错;3.R包过时;4.版本不匹配
  • 是否更新,是否:先拒绝no,不可以在更新
  • 依赖包报错或者版本就,单独装依赖包/更新

3. 条件语句来安装R包

if(FALSE) 则后面的代码被跳过
if(TRUE) 则后面的代码执行

if(!require(strings))install.packages("strings")
if(!require(feather))install.packages("feather")

4. 其他R包知识(不重要)

  • 查看包中存在的函数:ls("package:stringr")

R包的如何使用:1、快速查看函数帮助文档?包的名字;2、浏览器搜索:R包名字 package,找到bioconductor官网的介绍;3、加载Vignettes,利用函数browseVignettes("stringr")
文件名称在代码中出现必然以字符串形式存在,并存在于实际参数的位置上

工作空间管理

        工作空间是R语言的工作环境,所有创建的对象都被临时保存在工作空间中,可以用函数ls()列出当前工作空间中的所有对象:

 也即是Rstudio中资源环境中的所有对象。在退出R时,如果选择保存工作空间,R将会在工作空间所在的文件夹中创建两个新的文件。之前在R中输入的任何命令都将保存到一个名为.Rhistory的文件中,而当前的工作空间中的所有对象将保存在.Rdata的文件中。两个文件都没有前缀

工作目录:是R用来读取文件和保存结果的一个文件夹。

getwd()能展示目前的工作目录。

setwd()设定当前的工作目录

getwd()

想要把当前的工作空间保存到一个指定的文件:

save("myfile.Rdata")

myfile.Rdata将会保存在当前的工作目录下。下次调用只需要直接load(“文件名.Rdata”)即可。

基本运算

二、R的数据结构

1. 数据类型

1.数值型 numeric 1,2,3
2.字符型 character “a",'mm'
3.逻辑值 logical TRUE;FALSE;NA
NA表示存在但未知,NULL表示不存在

class()判断数据类型的函数:

常见的错误

class(a)

输出为没有object:a,表示没有定义数据a是什么。

calss("a")

class写错

class(true)

系统默认的逻辑值TRUE,一旦改变任何一个大小写,都会被认为是对象object,因此输出为找不到对象true

class(3)

使用了中文括号

R语言常见的报错:

function在R中表示函数;object表示对象;TRUE必须大写,R中严格区分大小写;括号必须用英文,unexpected input in "class("表示问题出现在(这里
#unepected出现表示代码写错了;找不到对象往往是没有引号或者没有定义对象

2. 数据类型的转换和判断

#is.numeric() 是否是数值型                                                                                              #is.logical() 是否是逻辑型
#is.character() 是否是字符型
#as.numeric()  转化为数值型
#as.character() 转化为字符型
#as.logical() 转化为逻辑型

is.numeric(3)
is.numeric("4")
as.numeric("jimmy")
class(as.numeric("jimmy"))  #s说明NA这里是数值型

3.数据结构

数据结构: 向量;数据框;矩阵;列表

3.1 向量

用于存储数值型、字符型、逻辑型数据的一维数组。函数c()可以用来创建向量。每一个向量中数据的类型必须一致,仅为一种数据类型。

修改向量中的元素 ,R语言中任何修改都要赋值,没有赋值就没有发生过

3.1.1 向量的生成

方法一:用 c() 结合到一起

c(2,5,6,2,9) 
c("a","f","md","b")

方法二:连续的数字用冒号“:”

x <- 1:5

方法三:有重复的用rep(),有规律的序列用seq(),随机数用rnorm()

rep("x",times=3)  
seq(from=3,to=21,by=3)  #从3开始到21,每3个数取一个数
rnorm(n=3) #生成3个随机数

方法四:通过组合,产生更为复杂的向量

paste0(rep("x",times=3),1:3) 
#表示将向量1与向量2联合在一起,如向量1是xxx,向量2是1,2,3,组合在一起为X1,X2,X3

3.1.2 向量的计算

max(x) #最大值
min(x) #最小值
mean(x) #均值
median(x) #中位数
var(x) #方差
sd(x) #标准差
sum(x) #总和
scale(x) #将x标准化
range(x) #求x的全距
quantile(x) #求x的分位数
length(x) #长度 向量中元素的个数
unique(x) #去重复,向量从左到右第二次或多次出现的取值去除。
duplicated(x) #对应元素是否重复,判断值为逻辑值,如果需要将重复的值结果为FALSE,需要在前面加入!函数
table(x) #重复值统计,计算每个取值的重复个数
sort(x) #排序,默认从小到大
sort(x,decreasing = F)
sort(x,decreasing = T)

3.1.3 向量的比较

x = c(1,3,5,1)
y = c(3,2,5,6)

(1)比较运算,生成等长的逻辑向量,对应位置的数据进行比较

x == y 
y == x

不同长度的向量比较

x = c(1,3,5,6,2)
y = c(3,2,5)
x == y #循环补齐,输出结果为最长的元素个数逻辑值。

 利用循环补齐简化代码:

paste0(rep("x",3),1:3)
paste0("x",1:3)

(2)数学计算

x + y

(3)连接

paste(x,y,sep=",")   #paste表示将两个元素连接在一起,seq表示分隔

 paste与paste0的区别

paste(x,y)
paste0(x,y)  #paste0两个元素之间无缝连接,paste默认有空格连接,或者设置相应空格
paste(x,y,sep = "")
paste(x,y,sep = ",")

paste可以连接两个或者多个对象,输出为字符型结果:

paste(rep("student",time=3),4:6,rep("class",time=3),sep="a")
paste(rep("student",time=3),4:6,rep("class",time=3),sep=",")
paste(rep("student",time=3),4:6,rep("class",time=3))
paste0(rep("student",time=3),4:6,rep("class",time=3))

(4)向量之间的交集、并集、差集

intersect(x,y) #交集
union(x,y) #并集
setdiff(x,y)  #差集 在x中有y中没有的
setdiff(y,x) #差集 在y中有x中没有的
setequal(x,y) #判断两个向量是否相等,输出为逻辑值
x %in% y #x的每个元素在y中存在吗
y %in% x #y的每个元素在x中存在吗

(5)向量取子集

核心思想:[ ]将TRUE对应的值挑选出来,FALSE丢弃

x <- 8:12

根据逻辑值取子集,[ ]内为逻辑值相关的运算,括号内只能是逻辑值

x[x==10] #第一个x表示从什么向量中挑选,括号内为挑选的条件,需要与x等长的逻辑值
x[x<12]
x[x %in% c(9,13)]

根据位置取子集,只支持数据,不支持逻辑值

x[4]
x[2:4]
x[c(1,5)]
x[-4] #-4不选第四个,保留剩下的,-表示反选
x[-(2:4)]
x[1,5] #错误:因为不是一个向量,2:4是向量,c(1,5)也是向量,所以[]内必须是X的下标组成的向量

补充:元素的名字

scores = c(100,59,73,95,45)
names(scores) = c("jimmy","nicker","Damon","Sophie","tony") #元素的名字,本质还是向量
scores
scores["jimmy"]
scores[c("jimmy","nicker")]

names(scores)[scores>60]

虽然score是向量,但是可以给向量赋予名字,再去取子集。

3.2 矩阵

矩阵是一个由行和列组成的二维数组。矩阵中每个元素具有相同的模式(数值型、字符型或逻辑型)。函数matrix()常用于创建矩阵。nrow指定行数,并自动计算出列数。byrow默认为FALSE,即是按列将数值进行排列,如果需要按行进行排列,着byrow=TRUE。

m <- matrix(1:9, nrow = 3)  #ncol是列,只需要写一个,另一个就默认了
colnames(m) <- c("a","b","c") #加列名

3.2.1 矩阵取子集:矩阵取子集不支持$,$只能用于数据框格式

m
m[2,]  #不支持$的使用
m[,1]
m[2,3]
m[2:3,1:2]
m

3.2.2 矩阵转置:把矩阵的行和列变换

t(m)

3.2.3 矩阵乘法:运算符号为%*%,需要第一个矩阵的列数等于第二个矩阵的行数

mat1 <- matrix(1:6,nrow=3)
mat2 <- matrix(5:10,nrow=2)
dim(mat1)#计算矩阵的维度,也即是行和列数
dim(mat2)
mat1%*%mat2

得到一个3x3的矩阵

3.2.4 矩阵的行列式和逆矩阵,可以使用函数det()和solve()实现

mat3 <- matrix(1:4,nrow=2)
det(mat3) #方阵的行列式
solve(mat3) #逆矩阵

3.2.5 对矩阵行列进行计算

rowSums(mat1)#对矩阵行进行求和
colSums(mat2)#对矩阵列进行求和
rowMeans(mat1)#对矩阵行进行求均值
colMeans(mat2)#对矩阵列进行求均值

3.3 数组

数组是多维数组,与矩阵相似,但是维度大于2。数组有一个特殊的维度属性dim。一个向量,加上维度属性后定义了一个数组。

A <- 1:24
dim(A) <- c(3,4,2)#3行4列,两个维度
A

除此之外还可以使用函数array()创建

3.4 列表

可以由不同类型的对象混合组成。

l <- list(m1 = matrix(1:9, nrow = 3),
          m2 = matrix(2:9, nrow = 2))
l

l[[2]] #提取出的是一个矩阵,l[2]则提取出的是列表
l$m1

3.5 数据框(重点)

数据框是一个由行和列构成的二维结构,行表示观测或记录,列表示变量或指标。与矩阵不同的是,数据框的不同列可以是不同的数据类型。使用data.frame()创建。

df1 <- data.frame(gene   = paste0("gene",1:4),
                  change  = rep(c("up","down"),each = 2),
                  score   = c(5,3,-2,-4))
df1 #每一列是一个向量,列名=列的内容

3.5.1 数据框的属性

dim(df1)  #显示数据框的维度,几行几列
nrow(df1)  #行数
ncol(df1) #列数

rownames(df1)  #提取df1行名
colnames(df1)  #提取df1列名

3.5.2 数据框取子集

按$列名提取

df1$gene

按坐标

df1[2,2] #第2行,第2列
df1[2,] #第2行,所有列
df1[,2] #所有行,第2列
df1[c(1,3),1:2] #第1,3行,第1,2列

按名字

df1[,"gene"]
df1[,c('gene','change')] #$只能提取一列,这种麻烦的方式可以同时取出多列

按条件(逻辑值)

df1[df1$score>0,]
df1[df1$change=="up",] #up是字符型,必须打上引号,不然会报错

如何取数据框的最后一列?

df1[,3] #只能取第三列,如果数据框存在多列,则不能用3取最后一列
df1[,ncol(df1)] #当不知道数据框最后一列时,只能用ncol()取数据框的最后一列

如何取数据框除了最后一列以外的其他列?
 

df1[,-ncol(df1)]  #减号只能用在数字,感叹号用在逻辑值

筛选score > 0的基因

df1[df1$score > 0,1]
df1$gene[df1$score > 0]  ##取子集的逻辑值向量,只需要与x对应,不必由x产生

3.5.3 数据框的修改

值的修改:

#改一个格
df1[3,3] <- 5
df1
#改一整列
df1$score <- c(12,23,50,2)     
df1
#新增一列p value
df1$p.value <- c(0.01,0.02,0.07,0.05) 
df1

行列名称的修改:

#改行名和列名,本质就是修改向量
rownames(df1) <- c("r1","r2","r3","r4")
#只修改某一行/列的名
colnames(df1)[2] <- "CHANGE" #对列名取子集第二列出来,改为“CHANGE”

数据框的连接:

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")
merge(test1,test3,by.x = "name",by.y = "NAME")  
#merge默认是交集,其他需要查看帮助菜单?merge

三、导入/导出数据

获取内置数据集

library(MASS)#载入R包
data(bacteria)#使用data函数调出数据集

获取其他格式的数据

CSV格式(本质是纯文本格式)的打开方式:1.excel打开;2.记事本打开;3.sublime;4.R语言读取:read.csv()

分隔符:逗号,空格,制表符(\t)

  • CSV:comma separated values逗号分隔文件;
  • TSV:Tab separated values Tab分隔值文件

表格文件读入R语言中,就得到一个数据框,对数据框进行修改不会同步到表格中

1. 导入数据

read.csv() 读取CSV格式文件
read.table() 读取txt格式文件                                                                                                             

(1)行名和列名的正确识别

ex1 <- read.table("ex1.txt") 
#R语言不能识别到列名,重新分配了列名V1-V5,会将数字转化为了字符型
ex1 <- read.table("ex1.txt",header = T)

当原始表格存在列名时需要设置参数header=T,让系统识别列名

(2)行列名中特殊符号的处理

ex2 <- read.csv("ex2.csv") #1.行名不能正确识别;2.列名将-改为了,;

 R语言中原始默认不存在特殊字符,就将-改为了.

ex2 <- read.csv("ex2.csv",row.names = 1,check.names = F) 
#row.name是一个行名向量,定义行名的名字;check.names=T会自动识别特殊字符并改为规范符号,F则默认

 (3)重复行名

rod <- read.csv("rod.csv",row.names = 1) #数据框不允许存在重复行名

系统会自动报错!!!

 (4)缺失值的处理

soft <- read.table("soft.txt") 

在第二行之后只存在四个值,第五列的值缺失,系统不能识别,因此不能读取

soft <- read.table("soft.txt",header = T,fill = T)

一般情况fill=T,默认将空格内容填充为NA,但是不能识别几个空格,可能出现串行没比如两个空格建,R语言就会认为只有一个空格,出现错误

soft <- read.table("soft.txt",header = T,sep = "\t")

制表符\t的设置表示一个制表符就是一个空格

 为了避免空格错位的问题:

read.delim()#读取txt文件,能避免上述问题
soft1 <- read.delim("sotf.txt")

其他格式:

read.xlsx( )读取Excel格式的文件,需要加载第三方包(例如openxlsx包,readx1包和gdata包);第二种方法将excel文件另存为csv格式,使用read.csv( )读取。

#如果没有安装请先安装
#install.packages("openxlsx")
#install.packages("readxl")
#install.packages("gdata")
library(openxlsx)
patients.data <- read.xlsx("patients.xlsx",sheet=1)
#sheet=表示读取的excel表格中第几个sheet

read.spss( )读取SPSS文件,read.xport( )读取SAS文件,read.dta( )读取Stata文件,但需要使用借助拓展包foreign包。foreign包主要功能读写其他格式的统计软件数据。

library(foreign)
patients.data <- read.spss("patients.sav",to.data.frame = TRUE)

To.data.frame参数的默认值为FALSE,如果不设置为TURE,返回的将是一个列表形式的数据。

2. 导出数据

数据框导出:

write.csv(test(数据框名称),file=“example.csv(输出的文件名称)”)
txt格式:write.table() eg:write(test,file="example.csv")

write.csv(soft,file="soft.csv")#一定要加后缀名.csv

Rdata格式:是R语言特有的数据储存形式,保存的是变量,不是表格
save()保存,load()加载;save(test,file="example.csv"),load("example.Rdata")

save(soft,file="soft.Rdata")#一定要加后缀名.Rdata
rm(list=ls())
load(file="soft.Rdata")

易犯错误:

save(soft,file="soft2.csv")

系统不报错,但是决定文件性质的是函数不是后缀。所以用excel/read.csv打开就是乱码,但可以使用Rdata语言打开,使用load函数。

3.  其他包导入/导出数据

(1)用rio包导入和导出数据

rio包提供一个类似于万能工具的包为目标,用统一的import()和export()函数简化用户导入和导出数据,此外convert()函数可以实现不同文件格式之间的转换。

以数据集infert为例:

data(infert)
library(rio)
export(infert,file="infert.csv")
#可以在工作目录下找到新生成的文件infert.csv的数据文件。
convert("infert.csv","infert.sav")
#将csv文件转换成为sav文件
infert.data <- import("infert.sav")
#将生成的infert.sav文件导入R中,命名为infert.data

import() 集成函数,根据文件的后缀选择相应的读取文件。
import_list()可以用来读取excel中存在多个工作簿的列表,输出形式为列表。

(2)其他包导入或导出文件

用于读取和导出文件的R包

  • #base包
  • #readr包
  • #data.table包
library(data.table) #不认识行名
a=fread("soft.txt") 

 因为不能识别行名,自动将行名设置为第一列

class(a) #存在data table的数据结构会影响后续分析

b=fread("soft.txt",data.table = F)#data.table=F能纯化为数据框结构
class(b)

参数data.table=F,可以将读取的文件直接设置为数据框格式,不用data.table格式。现在需要将数据框的第一列设置为行名。

rownames(b)=b[,1]#b第一列为行名
b=b[,-1]#第一列与行名重复,因此删除第一列名字。用-1表示删除第一列

四、数据框的常用操作

1.处理数据框的基本函数

加载数据集epiDisplay包中的Familydata

rm(list = ls())
#install.packages("epiDisplay")
library(epiDisplay)
data(Familydata)

1.1 查看数据框的前几行和后几行,head( )和tail( )函数。

head(Familydata,5)#不设置行数的话,默认为6行
tail(Familydata,3)

1.2 查看数据框变量名,names( )函数

names(Familydata)

1.3 数据框按照某个变量的值排序,order( )函数

Familydata[order(Familydata$age),]
Familydata[order(Familydata$age,decreasing = T),]
Familydata[order(-Familydata$age),]

本质跟取子集一样,按照age年龄大小进行排序,默认从小到大,如果想要从大到小增加参数decreasing=T。也可以使用age取相反数,在从小到大排序。

1.4 查找和删除重复数据

duplicated(Familydata$code)

duplicated( ) 函数用于查找是否有重复,第二次出现就会表示为重复,输出的值为逻辑值。因为输出的值比较时,难以肉眼检查是否存在重复值,可以使用函数table()统计FALSE和TRUE出现的频数,或any()用于检测逻辑值是否含有TRUE

any(duplicated(Familydata$code))
#结果为FALSE表示没有TRUE,没有重复值
table(duplicated(Familydata$code)) 
#输出的结果只有FASLE的频数,说明没有TRUE

删除重复数据

Familydata1 <- Familydata
Familydata1[12,] <- Familydata[2,]#给数据框增加一列重复的值
table(duplicated(Familydata1$code))#结果TRUE表示存在重复值

使用函数which( )可以找到变量code( )重复值所在的行

which(duplicated(Familydata1$code))

删除重复的行:利用取子集的思维,将子集中的TRUE提取出来,因此需要将不重复的FASLE转变为TRUE,重复值TRUE转为FALSE不提取出来。

Familydata2 <- Familydata1[!duplicated(Familydata1$code),]
identical(Familydata2,Familydata)#说明两个数据框一致

除了取子集外,函数distinct(数据框,去重的列,.keep_all=T)数据框按照某一列去重复,unique是去重复向量

distinct(Familydata1,code,.keep_all=T)

1.5 在数据框中删除和添加变量

使用$添加变量:

Familydata$log10money <- log10(Familydata$money)

使用函数transform()函数

Familydata <- transform(Familydata,log10money=log10(money))

使用取子集负号删除变量,负号不能用名称取。

Familydata <- Familydata[,-7]

1.6 把数据框添加到搜索路径

搜索路径的目的时因为在变量名称前面加上数据框名和符合$,这种方式有时候比较繁琐,一次函数attach可以将搜索的路径限定在数据框xxx中,直接输入变量名称即可。

函数attach( )可以将数据框添加到搜索路径中,detach()退出搜索路径。

attach(Familydata)
detach(Familydata)

2. 筛选行和列

案例:MASS包中birthwt数据集中包含189个研究对象,10个变量,一项关于新生儿低体重危险因素的病例对照研究。

2.1 筛选行:

library(dplyr)
data(birthwt,package = "MASS")

筛选变量年龄age大于35岁的所有记录:

#取子集的方法
birthwt[birthwt$age>35,]
#filter函数
filter(birthwt,age>35)

filter()函数,第一个参数是数据框名字,第二个参数级随后的参数是筛选数据框的表达式。

筛选体重大于4000g或小于2500的所有记录

filter(birthwt,bwt>4000|bwt<2500)
birthwt[birthwt$bwt>4000|birthwt$bwt<2500,]

如果有多个条件,可以用逗号隔开,例如筛选体重大于4000g或小于2500,年龄age大于35岁的所有记录

birthwt[(birthwt$bwt>4000|birthwt$bwt<2500)&birthwt$age>35,]
filter(birthwt,bwt>4000|bwt<2500,age>35)

函数slice()可以按照行号选择指定的行,第二行到第五行的所有记录

slice(birthwt,2:5)

2.2 选择列

函数select()用于选择数据框中的列(变量)

select(birthwt,age,bwt,race,smoke)

注意:MASS包中也有函数select,为了避免混淆如果需要同时加载两个包,可以使用dplyr::select()的格式完成。

3. arrange()排列行

除了基础包中的order之外,arrange函数也是可以将数据框记录按照某个变量进行排序的。

arrange(birthwt,bwt)
birthwt[order(birthwt$bwt),]

将变量bwt从小到大进行排序。如果需要从大到小排序,order的参数descreasing=T,arrange()函数的可以使用desc()函数实现或相反数。

birthwt[order(birthwt$bwt,decreasing = T),]
arrange(birthwt,-bwt)
arrange(birthwt,desc(bwt))

当存在多个变量的排序时,按照顺序一次添加即可,首先排序的变量放在第一个,然后第二个

arrange(birthwt,bwt,age)

先按bwt从小到大排序,存在重复相同数字时,按照age年龄进行从小到大排序。

4.添加新的变量

除了基础方法中的$和transform之外,还可以使用函数mutate()。第一个参数就是数据框名称,第二个参数为定义的数据内容,类似于transform函数。

mutate(birthwt,lwt.kg=lwt*0.4536)
transform(birthwt,lwt.kg=lwt*0.4536)

5. 拆分数据框

函数group_by( )可以将数据框按照某一个或某几个分类变量拆分成为多个数据框。

输出的数据框虽然外观没有改变,但是已经按照race的三个值分为三个数据框,在进行dplyr包的后续计算会产生三个不同的值,比如:

summarise(group_by(birthwt,race),mean.bwt=mean(bwt),sd.bwt=sd(bwt))

按照race分类变量,计算各组中的出生体重的平均值和标准差。

summarise()函数可以用于计算数据框某个变量的指定统计量

格式:summarise(数据框,生成统计量名称=统计函数(变量))如果有多个可以用逗号隔开。

tibble是tidyberse系列包(dplyr包)提供的一种类似于数据框的格式。

6. 数据框的合并

1. 按照某个共有变量合并

数据框的连接除了merge()函数默认取交集外,还可以使用dplyr包中的jion()函数。

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

  • inner_join( ) 取交集
  • right_join()右连接
  • left_join ()左连接
  • full_join ()全保留
  • semi_join ()半连接:一个表根据另一个表取子集,类似于交集,但是输出的数据框只有第一个数据框的变量,不是两个数据框的全部变量
  • anti_join ()反连接:根据一个表对另一个表中没有的对象取子集
library(dplyr)
inner_join(test1,test2,by="name")
right_join(test1,test2,by="name")
left_join(test1,test2,by="name")
full_join(test1,test2,by="name")
semi_join(test1,test2,by="name")
anti_join(test1,test2,by="name")

 注意两者的区别!

2. 纵向合并

要纵向合并两个数据框可以使用rbind()函数。前提:两个被合并的数据框必须拥有相同的变量,通常用于合并数据框中的观测。

data1 <- data.frame(id=1:5,
                    sex=c(0,1,1,0,1),
                    age=c(32,46,25,42,29))
data2 <- data.frame(id=6:10,
                    sex=c(1,0,1,1,0),
                    age=c(52,36,28,34,26))
rbind(data1,data2)

                                     

3. 横向合并

横向合并两个数据框,可以使用cbind()函数,前提:用于合并两个数据框必须拥有相同的行数。

data3 <- data.frame(days=c(28,57,15,7,19),
                    outcome=c("discharge","dead","discharge","dead","dead"))
cbind(data1,data3)

                              

7. %>%的传递操作

library(dplyr)
x1=filter(iris,iris$Sepal.Width>3) #筛选行
x2=select(x1,Sepal.Length,Sepal.Width) #筛选列
x3=arrange(x2,Sepal.Length) #从小到大排序
x4=arrange(x2,desc(Sepal.Length)) #从大到小排序

多次赋值,产生多个变量,x2和x1是中间变量,没有用容易让数据表格更加繁琐。

x=iris %>% 
  filter(Sepal.Width>3) %>%
  select(Sepal.Length,Sepal.Width) %>%
  arrange(Sepal.Length)

8. 数据框长宽格式转换

长格式:每次观测作为一条记录,所以一个观测对象可能占有多行。

宽格式:一个对象的多个不同时间点的观测都记录在同一行里,即是一个观测对象只占一行。

案例:以数据集Indometh,该数据集关于药物吲哚美辛的药物代谢动力学数据,一共6个试验对象,每名对象在连续8小时内定时测试血液中的药物浓度,一共测定了11次的值

这是一个典型的长数据格式,一个观测对象具有不同时间测试结果。

方法一:基础包中reshape()函数

#长数据转为宽数据
wide <- reshape(Indometh,
                v.names = "conc", #结果变量的值
                idvar = "Subject", #观测对象的id
                timevar = "time", #时间变量/也即是多次测量的变量
                direction = "wide")

#宽数据转为长数据
long <- reshape(wide,
                idvar = "Subject", #观测对象的id
                varying = list(2:12), #需要合并的列
                v.names = "conc", #合并后值得名称
                direction = "long")

time不能识别出具体的时间,只能以1,2,3这样进行分组。

方法二:tidyr包中pivot_wider()函数用于长格式转为宽格式,pivot_longer()用于把宽格式转换为长格式

library(tidyr)
wide <- pivot_wider(as.data.frame(Indometh),
                    names_from = time, #分组名称
                    values_from = conc) #变量值
wide

因为Indometh不是数据框格式,所以需要将转化为数据框格式,如果是数据框格式,直接输入数据名称。

long <- pivot_longer(wide,-Subject, #-观测ID名称
                     names_to = "time",#合并后的组名
                     values_to="conc") #变量值组的名称

一个整洁的数据集应该满足:每一行为一个观测,每一列代表一个变量。在对医学数据进行分析之前,通常情况下应先把数据集转换为长格式。

9. 缺失值处理

9.1 识别缺失值

判断是否是缺失值NA,is.na( )函数,当数量较多时,需要用table函数统计频数便于找到NA。

height <- c(100,150,NA,160)
is.na(height)
table(is.na(height))

 注意:任何包含NA的计算结果都是NA,如果需要计算统计量,需要将NA移除,一种方法是设置参数na.rm=T,一种是使用函数na.omit()把缺失值省略。

比如计算某变量的平均值

mean(height)
mean(height,na.rm = T)
mean(na.omit(height))

 函数summary()在计算向量的统计量时,会自动忽略缺失值,同时显示出缺失值的个数

summary(height)

9.2 探索数据框中的缺失值

案例:数据集iris,包含了150个鸢尾花样品,分为3个品种(species),每个品种各有50个样品,每个样品的四种属性,即花萼长度(Sepal.Length)、花萼宽度(Sepal.Width)、花瓣长度(Patal.Length)和花瓣宽度(Patal.Width)。数据集不含缺失值,missForest包中的prodNA随机生成缺失值。

#install.packages("missForest")
library(missForest)
set.seed(1234)  #设置随机数种子
iris.miss <-prodNA(iris) #默认生成数据10%的随机缺失值
summary(iris.miss)

 9.3 缺失值的处理

处理缺失值可以采用3种方法:1.删除,删除带有缺失值的变量或记录;2.替换,用均值、中位数、众数或其他值替代缺失值;3.补全,基于统计模型推测和补充缺失值。

删除:当缺失值的数量比较少,删除后对分析结果影响不大,可以使用函数na.omit()删除数据框中的缺失值。

#方法一:
iris.sub <- na.omit(iris.miss)
nrow(iris.sub)
#方法二:
iris.sub <- iris.miss[complete.cases(iris.miss),]

结果输出为97,也即是只有97列是完整的记录。complete.cases表示如果数据框种有一行有一个缺失值就输出FALSE,完整数据输出为TRUE,通过取子集的方法把TRUE提出出来,也即是完整数据。

使用特定数值替代缺失值:

以变量Spetal.Length为例,用忽略缺失值后的均值替代缺失值

Sepal.Length.Mean <- mean(iris.miss$Sepal.Length,na.rm = T)
Sepal.Length.Mean
iris.miss1 <- iris.miss#便于后面仍然可以使用iris.miss作为案例
iris.miss1$Sepal.Length[is.na(iris.miss1$Sepal.Length)] <- Sepal.Length.Mean
#提取出向量中缺失值,将其赋值给均值

多重插补:是一种基于重复模拟的处理缺失值的方法,常用于处理较为复杂的缺失值问题。R中有多个可以实现缺失值多重插补的包,Amelia包,mice包,mi包。

其中mice包使用链式方程的多变量补全法,被广泛用于数据清洗的过程。常用的方法有:(1)预测均值匹配(pmm)实质上就是线性回归,适用于数值型变量;(2)Logistic回归(logreg):适用于二分类变量;(3)多分类Logistic回归(ployreg),适用于无序多分类变量;(4)比例优势比模型(polr),适用于有序多分类变量。

#install.packages("mice")
library(mice)
imputed.data <- mice(iris.miss,seed=1234)
summary(imputed.data)

 在predictorMatrix中每一行代表含有缺失值的变量,如果该行对应的列元素为1,则代表该列变量被用于建模预测。mice输出的结果是一个列表,其中imp也是一个列表,存放着每个变量缺失值的插补值。

imputed.data$imp$Sepal.Length

 函数mice()默认进行5次随机抽样,得到的5次随机抽样的插补值。可以选择其中一组来进行插补。

complete.data <- complete(imputed.data,3)
complete.data

函数complete( )表示提取补全的数据,使用第三组数据补全缺失值。

10. 条件循环语句

10.1 条件语句

条件语句基本结构:

if(是一个逻辑值,不可是多个逻辑值组合成的向量){CODE1}else{CODE2}

if()里面的逻辑值是TRUE,后面大括号内的语句就会被执行,否则反正

i=-1
if(i<0){print("up")} #i=-1<0则为TURE,这运行print “up“
if(i>0){print("up")}
i=9
if(i<0){print("UP")}else{print("down")}

 ifelse()#具有三个重要参数:x逻辑值,yes逻辑值为TRUE时返回的值,no逻辑值为FALSE时返回的值

ifelse(i>0,"+","-")#如果i>0则输出+,否则输出-
x=rnorm(3)
ifelse(x>0,"+","-")
if(x>0{print("+")}else{print("-")})#报错

if只支持单个逻辑值,不支持逻辑值向量;ifelse既支持单个逻辑值,也支持多个逻辑值组合成为向量

非常重要的组合操作

ifelse()+str_detect(),王炸,可以实现分组

library(stringr)
samples = c("tumor1","tumor2","tumor3","normal1","normal2","normal3")
k1 = str_detect(samples,"tumor");k1 #逻辑值向量
ifelse(k1,"tumor","normal")
k2 = str_detect(samples,"normal");k2 #逻辑值向量
ifelse(k2,"normal","tumor")

如果有多个条件就逐一嵌套:

i = 0
if (i>0){
  print('+')
} else if (i==0) {
  print('0')
} else if (i< 0){
  print('-')
}

ifelse(i>0,"+",ifelse(i<0,"-","0"))

10.2 循环语句

10.2.1 For循环

模板:for(i in x){code}

x <- c(5,6,0,3)
s=0
for (i in x){
  s=s+i
  print(c(i,s))
}

 循环的保存:

s = 0
result = list()
for(i in 1:length(x)){
  s=s+x[[i]]
  result[[i]] = c(x[[i]],s)
}
result
do.call(cbind,result)#把result的结果按列拼接
do.call(rbind,result) #按行拼接

 

10.2.2 下标循环

x <- c(5,6,0,3)
s = 0
for (i in 1:length(x)){ #length(x)表示x的长度,i表示下标,1,2,3,4
  s=s+x[[i]] #直接用两个中括号,没有理由
  print(c(x[[i]],s))
}

11. 分割列数据和合并列数据

函数separate()将数据的一列分割为多列。

生信数据常用一些分隔符,比如chr1:pos1-pos2

method <- data.frame(coord=c("chr8:11666485-11666694","chr12:123215010-123215553","chr20:36148133-36149750")) %>%
separate(col=coord, #要分割的列
         into=c("chr","pos"), #分割成几列就写几列名字
         sep=":") #列的分隔符是什么
method

                                    

                 分割前                                                                     分割后

注意:%>%必须有不然,会报错

函数unite()将数据的多列分割为一列

iris %>%
  unite(col = "new col", #需要合成的列名
        Petal.Width:Species, #需要合成的列
        sep = "//") #分隔符符号

 

 

12. 字符串常用函数

  • str_length( ) 字符串长度
  • str_split( ) 字符串拆分
  • str_sub( ) 按位置提取字符
  • str_detect( ) 字符检测
  • str_replace/str_replace_all( ) 字符替换
  • str_remove/str_remove_all( ) 字符删除
x="my name is jimmy"
str_length(x) 
#str_length是计算字符串长度,包括空格,所以输出结果为16
length(x) 
#输出结果为1,因为x在引号内作为一个值

str_split(x," ")
#输出的结果为一个列表格式,需要用取子集的方式将字符串单独保存成一个向量
x2=str_split(x," ")[[1]];x2
x2[2]

当需要将拆分的字符串组合成一个表格

y=c("jimmy 150","Tom 148","Tina 146")
str_split(y," ")
str_split(y," ",simplify = T) #组合形成矩阵

                           

str_sub(x,4,8) #提取x中第4个到第8个字符

 

str_detect(x2,"y") #分别检测字符中是否含有y字母
#前面已经将x拆分成了多个字符串,并组合成为向量
str_starts(x2,"n")#以n开头
str_ends(x2,"e")#以e结尾

x2
str_replace(x2,"m","n") #只替换每一个字符串第一个检测到的字符
str_replace_all(x2,"m","n") #替换所有字符

x
str_remove(x," ")
str_remove_all(x," ")

13. 大型数据集的处理策略

13.1 清理工作空间

在启动任何新的分析项目时,首先清空工作空间,前提需要的内容保存成.Rdata

rm(list=ls())
rm(list=ls(all=T))

ls( )用于显示当前工作空间中的对象,all=T是为了清理包括隐藏对象在内的所有对象,默认值all=FALSE。

13.2 快速读取csv文件

read.csv在读取大型数据集时速度较慢,有时会报错,可以使用readr包中read_csv( )函数或者data.table包中的fread( )函数读取数据

13.3 剔除不需要的变量

bigdata <- as.data.frame(matrix(rnorm(5000*200),ncol=200))
varnames <- NULL
for (i in letters[1:20]) {
  for (j in 1:10) {
    varnames <- c(varnames,paste(i,j,sep = "_"))
    
  }
  
}
names(bigdata) <- varnames
names(bigdata)

创建了一个200个变量,5000个观测对象的数据集。利用两个for循环和R内置的字母数据设置变量名称。

在正式分析之前需要将用不上的变量暂时剔除,减少内存负担。

剔除的方法:联合dplyr包中的select( )函数和tidyselect包中的starts_with( )、end_with( )、contains( )等函数。

选择以a开头的变量:

subdata1 <- select(bigdata,starts_with("a"))

选择以2结尾的变量:

subdatda2 <- select(bigdata,ends_with("2"))

多个筛选条件时,可以使用函数vars()包括多个条件,select_at()筛选

subdata3 <- select_at(bigdata,vars(starts_with("a"),starts_with("b")))

选择变量中包含1的变量

subdata4 <- select(bigdata,contains("1"))
subdata4 <- select_at(bigdata,vars(contains("1")))

剔除以a开头的变量,2结尾的变量,包含1的变量

subdata5 <- select(bigdata,-starts_with("a"))
subdata5 <- select(bigdata,-ends_with("2"))
subdata5 <- select_at(bigdata,vars(-starts_with("a"),-starts_with("b")))
subdata5 <- select_at(bigdata,vars(-contains("1")))

 

13.4 选取数据集的一个随机样本

对大型数据集的全部记录进行处理往往会降低分析效率,在编写代码时,可以只抽取一部分记录对程序进行测试,以便优化代码并消除bug。

sampledata1 <- sample_n(subdata5,size = 500)
sampledata2 <- sample_frac(subdata5,size = 0.02)

函数sample_n()和sample_frac( )都用于从数据框中随机选取指定数量的行,前者中参数size用于指定行的个数,后者中的参数size用于指定所占行的比例。比如第一个表示,选取其中500例样本,第二个则表示选择其中2%的样本。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Dr_long1996/article/details/131091090

智能推荐

如何配置DNS服务的正反向解析_dns反向解析-程序员宅基地

文章浏览阅读3k次,点赞3次,收藏13次。root@server ~]# vim /etc/named.rfc1912.zones #添加如下内容,也可直接更改模板。[root@server ~]# vim /etc/named.conf #打开主配置文件,将如下两处地方修改为。注意:ip地址必须反向书写,这里文件名需要和反向解析数据文件名相同。新建或者拷贝一份进行修改。nslookup命令。_dns反向解析

设置PWM占空比中TIM_SetCompare1,TIM_SetCompare2,TIM_SetCompare3,TIM_SetCompare4分别对应引脚和ADC通道对应引脚-程序员宅基地

文章浏览阅读2.5w次,点赞16次,收藏103次。这个函数TIM_SetCompare1,这个函数有四个,分别是TIM_SetCompare1,TIM_SetCompare2,TIM_SetCompare3,TIM_SetCompare4。位于CH1那一行的GPIO口使用TIM_SetCompare1这个函数,位于CH2那一行的GPIO口使用TIM_SetCompare2这个函数。使用stm32f103的除了tim6和tim7没有PWM..._tim_setcompare1

多线程_进程和线程,并发与并行,线程优先级,守护线程,实现线程的四种方式,线程周期;线程同步,线程中的锁,Lock类,死锁,生产者和消费者案例-程序员宅基地

文章浏览阅读950次,点赞33次,收藏19次。多线程_进程和线程,并发与并行,线程优先级,守护线程,实现线程的四种方式,线程周期;线程同步,线程中的锁,Lock类,死锁,生产者和消费者案例

在 Linux 系统的用户目录下安装 ifort 和 MKL 库并配置_在linux系统的用户目录下安装ifort和mkl库并配置-程序员宅基地

文章浏览阅读2.9k次。ifort 编译器的安装ifort 编译器可以在 intel 官网上下载。打开https://software.intel.com/content/www/us/en/develop/tools/oneapi/components/fortran-compiler.html#gs.7iqrsm点击网页中下方处的 Download, 选择 Intel Fortran Compiler Classic and Intel Fortran Compiler(Beta) 下方对应的版本。我选择的是 l_在linux系统的用户目录下安装ifort和mkl库并配置

使用ftl文件生成图片中图片展示无样式,不显示_ftl格式pdf的样式调整-程序员宅基地

文章浏览阅读689次,点赞7次,收藏8次。些项目时需要一个生成图片的方法,我在网上找到比较方便且适合我去设置一些样式的生成方式之一就是使用Freemarker,在对应位置上先写好一个html格式的ftl文件,在对应位置用${参数名}填写上。还记得当时为了解决图片大小设置不上,搜索了好久资料,不记得是在哪看到的需要在里面使用width与height直接设置,而我当时用style去设置,怎么都不对。找不到,自己测试链接,准备将所有含有中文的图片链接复制一份,在服务器上存储一份不带中文的文件。突然发现就算无中文,有的链接也是打不开的。_ftl格式pdf的样式调整

orin Ubuntu 20.04 配置 Realsense-ROS_opt/ros/noetic/lib/nodelet/nodelet: symbol lookup -程序员宅基地

文章浏览阅读1.5k次,点赞6次,收藏12次。拉取librealsense。_opt/ros/noetic/lib/nodelet/nodelet: symbol lookup error: /home/admin07/reals

随便推点

操作系统精选习题——第四章_系统抖动现象的发生由什么引起的-程序员宅基地

文章浏览阅读3.4k次,点赞3次,收藏29次。一.单选题二.填空题三.判断题一.单选题静态链接是在( )进行的。A、编译某段程序时B、装入某段程序时C、紧凑时D、装入程序之前Pentium处理器(32位)最大可寻址的虚拟存储器地址空间为( )。A、由内存的容量而定B、4GC、2GD、1G分页系统中,主存分配的单位是( )。A、字节B、物理块C、作业D、段在段页式存储管理中,当执行一段程序时,至少访问()次内存。A、1B、2C、3D、4在分段管理中,( )。A、以段为单位分配,每._系统抖动现象的发生由什么引起的

UG NX 12零件工程图基础_ug-nx工程图-程序员宅基地

文章浏览阅读2.4k次。在实际的工作生产中,零件的加工制造一般都需要二维工程图来辅助设计。UG NX 的工程图主要是为了满足二维出图需要。在绘制工程图时,需要先确定所绘制图形要表达的内容,然后根据需要并按照视图的选择原则,绘制工程图的主视图、其他视图以及某些特殊视图,最后标注图形的尺寸、技术说明等信息,即可完成工程图的绘制。1.视图选择原则工程图合理的表达方案要综合运用各种表达方法,清晰完整地表达出零件的结构形状,并便于看图。确定工程图表达方案的一般步骤如下:口分析零件结构形状由于零件的结构形状以及加工位置或工作位置的不._ug-nx工程图

智能制造数字化工厂智慧供应链大数据解决方案(PPT)-程序员宅基地

文章浏览阅读920次,点赞29次,收藏18次。原文《智能制造数字化工厂智慧供应链大数据解决方案》PPT格式主要从智能制造数字化工厂智慧供应链大数据解决方案框架图、销量预测+S&OP大数据解决方案、计划统筹大数据解决方案、订单履约大数据解决方案、库存周转大数据解决方案、采购及供应商管理大数据模块、智慧工厂大数据解决方案、设备管理大数据解决方案、质量管理大数据解决方案、仓储物流与网络优化大数据解决方案、供应链决策分析大数据解决方案进行建设。适用于售前项目汇报、项目规划、领导汇报。

网络编程socket accept函数的理解_当在函数 'main' 中调用 'open_socket_accept'时.line: 8. con-程序员宅基地

文章浏览阅读2w次,点赞38次,收藏102次。在服务器端,socket()返回的套接字用于监听(listen)和接受(accept)客户端的连接请求。这个套接字不能用于与客户端之间发送和接收数据。 accept()接受一个客户端的连接请求,并返回一个新的套接字。所谓“新的”就是说这个套接字与socket()返回的用于监听和接受客户端的连接请求的套接字不是同一个套接字。与本次接受的客户端的通信是通过在这个新的套接字上发送和接收数_当在函数 'main' 中调用 'open_socket_accept'时.line: 8. connection request fa

C#对象销毁_c# 销毁对象及其所有引用-程序员宅基地

文章浏览阅读4.3k次。对象销毁对象销毁的标准语法Close和Stop何时销毁对象销毁对象时清除字段对象销毁的标准语法Framework在销毁对象的逻辑方面遵循一套规则,这些规则并不限用于.NET Framework或C#语言;这些规则的目的是定义一套便于使用的协议。这些协议如下:一旦销毁,对象不可恢复。对象不能被再次激活,调用对象的方法或者属性抛出ObjectDisposedException异常重复地调用对象的Disposal方法会导致错误如果一个可销毁对象x 包含或包装或处理另外一个可销毁对象y,那么x的Disp_c# 销毁对象及其所有引用

笔记-中项/高项学习期间的错题笔记1_大型设备可靠性测试可否拆解为几个部分进行测试-程序员宅基地

文章浏览阅读1.1w次。这是记录,在中项、高项过程中的错题笔记;https://www.zenwu.site/post/2b6d.html1. 信息系统的规划工具在制订计划时,可以利用PERT图和甘特图;访谈时,可以应用各种调查表和调查提纲;在确定各部门、各层管理人员的需求,梳理流程时,可以采用会谈和正式会议的方法。为把企业组织结构与企业过程联系起来,说明每个过程与组织的联系,指出过程决策人,可以采用建立过程/组织(Process/Organization,P/O)矩阵的方法。例如,一个简单的P/O矩阵示例,其中._大型设备可靠性测试可否拆解为几个部分进行测试