0%

R语言学习(一)基本容器

R语言是一门数据处理语言,本文记录R语言学习的过程和一些注意点

基本数据结构

对于数据集行和列的不同术语:

  • 统计学:观测(observation)/变量(variable)
  • 数据分析师:记录(record)/字段(field)
  • 机器学习与数据挖掘:示例(example)/属性(attribute)

R的数据结构包括向量,数组,数据框和列表,R可以处理的数据类型成为模式(modes),包括数值型,字符型,布尔型,复数型和原生型(字节)

向量,矩阵,数组的本质是数组,唯独分别是一维,二维,更高,三者必须有相同的模式,而列表每一个元素可以是不同类型,是一个广义表。

向量(Vector)

创建:

a <- c(1,2,3,4,5)
b <- c("one","two","three")
d <- c(1:10)

其中d是1~10的数组成的数组,R中a:b表示a~b的连续数组成的向量,自动推导升降序。

访问可以通过方括号里下标访问返回一个元素,也可以访问一个向量构成的下标,返回一个子向量

a[3]
a[c(1,3,5)
a(1:3)

矩阵(Matrix)

创建

矩阵构造至少要有三个参数,第一个是一维向量,第二三是行列元素数目,第三和第四可选,分别是是否按行填充(默认按列)和两个维度的属性名(包含了两个向量的list)

matrix <- matrix(vector,nrow=number_of_rows,ncol=number_of_columns,byrow=logical_value,dimnames=list(char_vector_rownames,char_vector_colnames))

例子:
cells <- c(1,26,24,68)
rnames <- c("R1", "R2")
cnames <- c("C1", "C2")
mymatrix <- matrix(cells, nrow=2, ncol=2, byrow=TRUE,
dimnames=list(rnames, cnames))
mymatrix

访问

m[1,2]
m[2,]
m[,3]
m[1,c(1,3)]

R中忽略某个位置的参数而使用逗号直接隔开,则该缺省属性视为通配符

数组(Arrays)

数组的维度可以大于2,可以理解为高维度的矩阵

创建

myarray <- array(vector,dimensions,dimnames)

其中vector包含了数组中的数据,dimensions是一个数值型向量,给出了各个维度下标的最大值,而dimnames是可选的、各维度名称标签的列表。

dim1 <- c("A1", "A2")
dim2 <- c("B1", "B2", "B3")
dim3 <- c("C1", "C2", "C3", "C4")
z <- array(1:24, c(2,3,4),dimnames=list(dim1, dim2, dim3))
z

访问

访问类似矩阵,z[1,2,3]可以具体对一个元素访问,也可以空缺某个参数或者填入向量,返回一个子数组

数据框(DataFrames)

创建

通过传入若干个向量的变长参数,每个属性的名称即为对应向量名

patientID <- c(1, 2, 3, 4)
age <- c(25, 34, 28, 52)
diabetes <- c("Type1", "Type2", "Type1", "Type1")
status <- c("Poor", "Improved", "Excellent", "Poor")
patientdata <- data.frame(patientID, age, diabetes,status)
patientdata

访问

patientdata[1:2] #选取第1、2列
patientdata[c("diabetes","status")]
patientdata[2,] #选取第2行
patientdata$age #选取age列
patientdata$age[2] #选取age列的第二个

$表示选取数据框中某个特定变量,相当于一般计算机语言中的.

搜索路径

比如,刚刚建立好上述patientdata的数据框后,可以访问age和status变量,则说明age和status在当前R的搜索路径中,此时执行rm agerm status则将这两个变量从搜索路径中删除,此时执行plot(age,status)来画图则会失败

attach()/detach()函数

attach()函数可以吧一个数据框添加到当前的搜索路径中:attach(patientdata),则此时agestatus则有在搜索路径中了,此时plot(age,status)又可以使用了

detach()函数可以将数据框从搜索路径中移除,当detach()造成数据对象重名时,原始对象将取得优先权。

with()函数

针对某一个数据框操作,可以用with(),不需要担心名称的冲突,这样可以避免频繁的atach()detach()

with(patientdata,{
plot(patientID,age)
plot(patientID,status)
})

当语句只有一条时,可以省略大括号

因子(Factors)

  • 数据类型分为:
    • 类别(nominal:糖尿病类型)
    • 有序(ordinal:病情好中坏)
    • 连续型(continuous:年龄)
  • 在R中,类别变量和有序变量称为因子。因子在R中非常重要,因为它决定了数据的分析方式以及如何进行视觉呈现

    factor()函数

    函数factor()以一个整数向量的形式存储类别值。
    diabetes <- c("Type1", "Type2","Type1","Type1")
    str(diabetes) #str()函数会输出一个R对象的结构
    #输出:chr [1:4] "Type1" "Type2" "Type1" "Type1"
    diabetes <- factor(diabetes)
    str(diabetes)
    #输出:Factor w/ 2 levels "Type1","Type2": 1 2 1 1
    对于字符类型的向量,因子的水平依据字典序创建,可以指定level选项来覆盖默认排序
    status <- factor(status,order=TRUE,levels=c("Poor","Improved","Excellent"))
    如果用字符向量创建数据框,R会将字符向量转换为因子,可以手动取消:最后一个参数设置为:stringAsFactors=FALSE

列表(List)

列表就是一些对象的有序集合。列表中可
能是若干向量、矩阵、数据框,甚至其他
列表的组合。例:

g <- "My First List"
h <- c(25, 26, 18, 39)
j <- matrix(1:10, nrow=5)
k <- c("one", "two", "three")
mylist <- list(title=g, ages=h,j, k)
mylist

列表是一个有下标的多类型的广义容器

关于NA

NA(Not Available),NaN(Not a Number),分别表示缺失值和不可能存在的值(例如除0的结果)。
将一个值赋给某个向量、矩阵、数组或列表中一个不存在的元素时,R将自动扩展这个数据结构以容纳新值,空缺的部分由NA填补;当访问一个容器不存在的位置的元素时,也会返回NA

  • 函数is.na()用以检测缺失值是否存在。
    y <- c(1, 2, 3, NA)
    #then the function
    is.na(y)
    #returns c(FALSE, FALSE, FALSE, TRUE)

缺失值参与函数计算和四则运算结果依然是缺失值,多数的数值函数都有一个na.rm=TRUE选项

x <- c(1, 2, NA, 3)
y <- sum(x, na.rm=TRUE)

na.omit()可以删除所有含缺失数据的行:

newdata <- na.omit(olddataframe)

注意:R中容器下标从1开始

数据的导入

edit()键盘输入

edit()会调用一个允许手动输入数据的文本编辑器

patientdata <- edit(patientdata)

edit()是基于对象的一个副本进行修改的,返回徐改后的副本

从带分隔符的文本(*.csv)导入数据

mydataframe <- read.table(file,header=logical_value,sep="delimiter",row.names="name")

read.table()从带分隔符的文本文件中导入数据,header表明首行是否包含了变量名,sep指定分隔符,row.names是一个可选参数,用以指定一个或多个标识符。

flights <- read.table("flights14.csv", header=TRUE, sep=",")

默认情况下,字符型变量将转换为因子

从Excel中导入

读取一个Excel文件的最好方式,就是在
Excel中将其导出为一个逗号分隔文件
(csv),再使用上一页的方式导入R中。

导入XML数据

R的XML包:
– 可用来解析处理XML或是HTML数据
– 还可以抓取网页数据
– 最重要两个函数是xmlTreeParse()和getNodeSet(),前者负责抓取页面数据并形成树状结构,后者对抓取的数据根据XPath语法来选取特定的节点集合。

导入SPSS数据

SPSS数据集可以通过foreign包中的函数read.spss()导入到R中,也可以使用Hmisc
包中的spss.get()函数。

install.packages("Hmisc")
library(Hmisc)
mydataframe <- spss.get("mydata.sav",
use.value.labels=TRUE)

mydata.sav是要导入的SPSS数据文件,use.value.labels=TRUE表示让函数将带有值标签的变量导入为R中水平对应相同的因子,mydataframe是导入后的R数据框。

导入SAS数据

SAS的版本更新可能会导致R中导入SAS数据集的函数失效。可以采用以下方法:

  1. 以在SAS中使用PROC EXPORT将SAS数据
    集保存为一个逗号分隔的文本文件
  2. 再使用处理csv的方法

访问数据库管理系统

例:

library(RODBC) #使用微软ODBC接口
myconn <-odbcConnect("mydsn", uid="Rob",pwd="aardvark")
crimedat <- sqlFetch(myconn, Crime)
#sqlFetch()将Crime表复制到R数据框crimedat中
pundat <- sqlQuery(myconn, "select * from Punishment")
#sqlQuery()非常强大,因为其中可以插入任意的有效SQL语句
close(myconn)

数据处理

变量与运算符

R是弱类型语言,类似python,动态类型变量,使用<-赋值,对于数据框,添加新属性和json操作类似,直接给某个属性赋值

运算符 描述
+
-
*
\
^或** 求幂
x%%y 取余
x%/%y 整除

变量冲编码

举例:一个调查问卷的数据框

manager <- c(1, 2, 3, 4, 5)
date <- c("10/24/08", "10/28/08", "10/1/08", "10/12/08", "5/1/09")
country <- c("US", "US", "UK", "UK", "UK")
gender <- c("M", "F", "F", "M", "F")
age <- c(32, 45, 25, 39, 99) #99代表年龄缺失
q1 <- c(5, 3, 3, 3, 2)
q2 <- c(4, 5, 5, 3, 2)
q3 <- c(5, 2, 5, 4, 1)
q4 <- c(5, 5, 5, NA, 2)
q5 <- c(5, 5, 2, NA, 1)
leadership <- data.frame(manager, date, country, gender, age, q1, q2,
q3, q4, q5, stringsAsFactors=FALSE)

变量冲编码是指修改容器中的数据,例如:
leadership$agecat[leader$age>75] <- "Elder"表示将leadership中age>75查询对应的agecat赋值为”Elder”,R中的[]用途类似定于表示限定,类似sql的where语句。

使用within()可以简化语法,对于leadership 数据框修改:

leadership <- within(leadership,{
agecat <- NA
agecat[age > 75] <- "Elder"
agecat[age >= 55 & age <= 75] <- "Middle Aged"
agecat[age < 55] <- "Young" })

注意within()也是基于副本操作,所以需要使用赋值语句来保存变化值,某一个成员都被赋成NA则该属性被视作删除

变量重命名

fix()可以调用一个交互式的编辑器,单击变量名,然后在弹出的对话框中将其重命名。例如:fix(leadership)

只用edit(X)在窗口中编辑修改X,关闭窗口后X没有改变,应使用 Y<- edit(X);使用fix(X)在窗口中编辑修改X,关闭窗口后X就是修改后的值,不必使用Y <- fix(X)

也可使用reshape报提供的rename()函数:

install.packages("reshape") #先安装包
library(reshape)
leadership <- rename(leadership,
c(manager="managerID", date="testDate")
)

方法三则是使用names()函数,该函数返回一个向量,包含了数据框的所有元素名称,对他操作则视作对数据框内元素名称的操作

#查看所有变量名
names(leadership)
#将第二个变量重命名
names(leadership)[2] <- "testDate"
#将q1到q5重命名为item1到item5
names(leadership)[6:10] <- c("item1","item2", "item3", "item4", "item5")

日期值

as.Date(x,"input_format")函数用于将字符串类型转化为日期类型,x是时间字符串,input_format是时间格式字符串(具体查阅ppt-3.23)

日期值的默认输入格式为yyyy-mm-dd

mydates <- as.Date(c("2007-06-22", "2004-02-13"))

在leadership数据集中,日期是以
mm/dd/yy的格式编码为字符型变量的。需要转化:

leadership$date <- as.Date(leadership$date,"%m/%d/%y")

Sys.Date()可以返回当天日期,date()可以返回当前日期和时间,format(x,format="output_format")as.Date()类似,后者基于副本操作返回新值,前者直接修改变量。

Date类型支持加减法,difftime(date1, date2, units="weeks")用于计算周数,as.character(dates)返回一个字符串,用于把日期转化为字符串。

数据类型转换

判断是数据类型:R提供了形如is.DataType()的函数,例如is.numeric(),is.character(),is.vector(),is.matrix,is.data.frame(),他们返回True或者False.

数据类型转化:R提供类似as.DataType()的函数,例如as.numeric(),as.character(),as.vector(),as.matrix,as.data.frame()他们转化原类型,返回新类型。

数据排序

使用order()函数对一个数据框进行排序。

newdata <- leadership[order(leadership$age),]

在排序变量的前边加一个减号即可得到降
序的排序结果。

newdata <- leadership[order(-leadership$age),]

多变量排序:
newdata <- leadership[order(leadership$gender,leadership$age),]

数据集的合并

数据集的合并用于增加变量或者增加观测

  • 横向合并:使用merge()函数,如果有一个或多个共同变量,则进行内联。

    total <- merge(dataframe1,dataframe2,by="ID")
    total <- merge(dataframe1,dataframe2,by=c("ID","Country"))
    • 横向合并:如果不需要指定一个公共索引,则可以直接使用cbind()函数

      total <- cbind(dataframe1,dataframe2)
    • 纵向合并:rbind()函数,两个数据框必须有相同的变量

      total <- rbind(dataframeA,dataframeB)

数据集的子集

可以通过下标选取数据的方式获得子集:

newdata <- leadership[, c(6:10)]

剔除数据:

myvars <- names(leadership) %in% c("q3", "q4")
newdata<-leadership[!myvars]

其中myvars是一个只包含布尔类型的变量的向量,传入[]中,返回对应为True的子数据框。

选取变量时采用逻辑型向量注意:

leadership[c(TRUE, FALSE, FALSE),]
# 如果行数大于3:会得到1、4、7、10、1316......行
leadership[c(TRUE, FALSE),]
# 如果行数大于2:会得到1、3、5、7......行

例如:删除第七和第八个变量

newdata <- leadership(c(-7,-8))

也可以这样删除:

leadership$q3 <- NULL

[]表示限定,用于选入观测:

newdata <- leadership[leadership$gender=="M"
&leadership$age > 30,]

subset()函数使用来选择变量和观测的最简单方法:

newdata <- subset(leadership, age >= 35 | age < 24, select=c(q1, q2, q3, q4))
newdata <- subset(leadership, gender=="M" & age > 25, select=gender:q4)

随机抽样

sample()可以从数据集中(有放回或无放回地)抽取大小为n的一个随机样本
例:从leadership数据集中随机抽取一个大小为3的样本

mysample <- leadership[sample(1:nrow(leadership),3,replace=FALSE)]

SQL语句操作数据框

安装sqldf数据包,install.packages("sqldf")

library(sqldf)
newdf <- sqldf("select * from .....")

数据框的转置

cars <- mtcars[1:5,1:4]
t(car) #对car转置

分类汇总

分类汇总的函数为aggregate(x, by, FUN),其中x是待分类汇总的数据对象;by是一个
变量名组成的列表,用于对原有观测进行分类;FUN是用来计算描述性统计量的函数,它将被用来计算新观测中的值。例:

options(digits=3) #保留3位有效数字
attach(mtcars)
aggdata <-aggregate(mtcars, by=list(cyl,gear),FUN=mean, na.rm=TRUE)

Reshape包

reshape包是一套整合和重构数据集的万能工具。首先将数据melt,使每一行都是一个唯一的标识符—变量组合,然后将数据cast为任何形状,在重铸过程中,可以使用任何函数对数据进行整合。

首先library(reshape2)

md <- melt(mydata,id=c("ID","Time")) #融化数据

之后newdata <- cast(md,formula,FUN),md是已经融化的数据,formula是想要的最后结果,FUN是可选的函数

例子:根据id求x1平均值

cast(md,id~x1,mean)

条件与循环

类似c语言的if else语法,注意else的匹配,} else {需要出现在同一行。
R中特有函数if(cond,statement1,statement2)

switch(i,
happy = "I am glad you are happy",
afraid = "There is nothing to fear",
sad = "Cheer up",
angry = "Calm down now"
) # 返回一个最终的结果

循环:for(variable in seq) statement, while(cond) statement

自定义函数

例子:

mydate <- function(type="long") { # 默认参数
switch(type,
long = format(Sys.time(), "%A %B %d %Y"),
short = format(Sys.time(), "%m-%d-%y"),
cat(type, "is not a recognized type\n"))
}

Disqus评论区没有正常加载,请使用科学上网