R语言入门
基本操作(包括读取数据)
设置工作目录
setwd('D://R/')
读取数据文件
listing<-read.csv('listings.csv',header = T,sep = ',',quote = '')
listings<-na.omit(listing) # 去除所有含缺失值的行
连接mysql数据库
方法一:RMYSQL包----中文会出现乱码
library(RMySQL)
con<- dbConnect(MySQL(),username = 'root',password='123',host="192.168.1.105",port=3306,dbname = 'ex') # 建立连接
dbSendQuery(con, 'SET NAMES gbk') # 设置数据库读取编码格式,避免造成中文数据出现乱码的情况
dbGetInfo(con) # 查询连接信息
dbListTables(con) # 查询数据库的表
data<-dbReadTable(con,"test_taobao") # 读整个表
data<-na.omit(data)
data$new_year<-as.numeric(data$yy)
summary(data)
rs <- dbGetQuery(con,'select * from test_taobao') # 用SQL语句提取数据
dbDisconnect(con) # 关闭连接
**** _******************忽略此内容 ** ** ** ** ** ** ** ** ** _
方法二:RODBC包建立连接----与数据库连接限制较多,但中文不会出乱码
需要先下载安装ODBC,建立与本机与数据库的连接后,通过建立的连接来进行数据读取
ODBC下载地址:https://dev.mysql.com/downloads/connector/odbc/
安装完成后,再电脑控制面板---管理工具--ODBC数据源(64位)——单击“添加”。选择mysql odbc 5.3 ansi driver
填写需要连接的数据库地址,端口号,选择数据库名
library(RODBC)
conn<-odbcConnect('sunhao',uid = 'root',pwd = '123456')
sqlTables(conn)
result<-sqlQuery(conn,'select * from sunhao')
result
** _**********************忽略结束** ** ** ** ** ** ** ** ** ** ** _
第一章 R的数据类型和数据类型的操作
数值(numberic)、字符串(character)、逻辑值(logical)、复数(complex)、缺失值(NA)
1 # 数值
‘sunhao’ # 字符串
TRUE # 逻辑型真
FALSE # 逻辑型假
T # 逻辑型真
F # 逻辑型假
1+2i # 复数
is.numeric(listings$price)
is.vector(listings$price)
数据类型 | 中文含义 | 判断函数 | 转换函数 |
---|---|---|---|
character | 字符串 | is.character() | as.character() |
numeric | 数值 | is.numeric() | as.numeric() |
logical | 逻辑 | is.logical() | as.logical() |
complex | 复数 | is.complex() | as.complex() |
NA | 缺失 | is.na() | as.na() |
向量(vector)、列表(list)、因子(Factor)
向量(向量内部的数据必须是同一种数据类型)
c(1,2,3,4,5,6) # 向量
c(1:10) # 向量,取1-10
a <- c('sunhao','haosun','haozi')
a[2] #向量取值
is.vector(a) #判断是否向量
列表(列表内部存的数据类型可以不是同一种数据类型
list_a <- list(student=c('sunhao','pingxinchuan'),score = c(21,31))
list_a
is.vector(list_a)
b <- as.list(a) # 将向量转换为列表
is.list(b) # 判断是否列表
因子(将向量转化为因子型,用于后面列联表分析及分组型变量的分析)
sex <- c('M','F','M','M','F')
is.factor(sex)
sex_factor <- as.factor(sex)
levels(sex_factor)
levels(sex) # 输出NULL,因为sex不是因子型数据类型
矩阵(matrix)、数组(Array)、数据框(Data frame)----数组和矩阵的运算涉及到线性代数的知识,暂时不讲
矩阵
matrix_a <- matrix(c(1:10),nrow = 2)
matrix_a
matrix_b <- matrix(c(1:10),nrow = 2,byrow=T)
matrix_b
数组(Array)三维
array1 <- array(1:18,c(3,3,2))
array1
dim1<-c('A1','A2','A3')
dim2<-c('B1','B2','B3')
dim3<-c('C1','C2')
array2 <- array(1:18,c(3,3,2),dimnames = list(dim1,dim2,dim3))
array2
array3 <- array(1:6,c(2,3))
array3
数据框(Data frame)
names <- c('A','B','C','D','E')
english <- c(60,62,80,90,95)
math <- c(80,88,90,65,70)
scores <- data.frame(names,english,math) # 数据框每一列的数量必须相同
scores
scores$names # 取数据框的names变量的值
scores[[1]] # 取数据框第一列的值
第二章 数据清洗
数据选择(数据框行列的选择、筛选、列操作)
b <- listings[1000,] # 中括号中用,分开,左边是行,右边选列,行列都可以写向量c(1,2,3)传给行,就是取第1,2,3行,传给列则是第一到三个变量(字段)
b <- listings[,c('price','room_type')] # 取listings表的price和room_type变量
b <- listings[c(100,200,300,400),] # 按向量提取数据,提取第100/200/300/400行的数据
b <- listings[c(100,200,300,400),c('price','room_type')] # 按向量提取数据,提取第100/200/300/400行的price和room_type数据
c <- listings[which(listings$room_type == 'Private room'),] # 按条件筛选,which返回的是行号
c <- listings[which(listings$room_type == 'Private room' |listings$room_type == 'Entire home/apt'),] # 按条件筛选,连接两个同时成立的条件用&,两个或关系用|
d <- listings$price^2/1000 # 由于单独取某一列及为向量,向量中如果是数值的话,可以直接做加减乘除等一般的数字计算
library(tidyr) # tidyr包,合并两列数据,不论是字符串还是数值,
new_lisitngs = unite(listings, "newtype2", room_type, neighbourhood, sep = "/", remove = FALSE) # 将room_type和neighbourhood变量合并,合并中间加/符号,remove传逻辑值,TURE代表合并后删除原变量,FALSE表示合并后保留原变量
数据分组、分割、合并和变形
tapply(listings$price,list(listings$neighbourhood,listings$room_type),FUN = mean) # 分组汇总,求各地区各种房型价格的均值,FUN传递需要计算的参数函数。
sc表
序号 | S_id | C_id | SCORE |
---|---|---|---|
1 | 1 | 01 | 80 |
2 | 1 | 02 | 90 |
3 | 1 | 03 | 99 |
4 | 2 | 01 | 70 |
5 | 2 | 02 | 60 |
6 | 2 | 03 | 80 |
7 | 3 | 01 | 80 |
8 | 3 | 02 | 80 |
9 | 3 | 03 | 80 |
10 | 4 | 01 | 50 |
11 | 4 | 02 | 30 |
12 | 4 | 03 | 20 |
13 | 5 | 01 | 76 |
14 | 5 | 02 | 87 |
15 | 6 | 01 | 31 |
16 | 6 | 03 | 34 |
17 | 7 | 02 | 89 |
18 | 7 | 03 | 98 |
student表
序号 | S_id | Sname | Sage | Ssex |
---|---|---|---|---|
1 | 1 | 赵雷 | 1990-01-01 | 男 |
2 | 2 | 钱电 | 1990-12-21 | 男 |
3 | 3 | 孙风 | 1990-05-20 | 男 |
4 | 4 | 李云 | 1990-08-06 | 男 |
5 | 5 | 周梅 | 1991-12-01 | 女 |
6 | 6 | _兰 | 1992-03-01 | 女 |
7 | 7 | 郑竹 | 1989-07-01 | 女 |
8 | 8 | 王菊 | 1990-01-20 | 女 |
merge函数链接两个表,all族参数代表是inner join/left join/right join,by族参数代表是on,通过什么来链接。
全链接(左右都要)
all_join <- merge(sc,student,all = T,by.x = 'S_id')
inner join
inner_join <- merge(sc,student,all = F,by.y = 'S_id')
left join
left_join <- merge(sc,student,all.x = T,by.x = 'S_id',by.y = 'S_id')
right join
right_join <- merge(sc,student,all.y = T,by.y = 'S_id')
缺失值、异常值和重复值处理
1. 缺失值
1.1查看是否有缺失值
summary(listing) # 使用summary函数,会返回每一列的缺失值数量
1.2删除缺失值行
listings <- na.omit(listing) # 删除listing里面含有缺失值的所有行
1.3替换缺失值
price_mean <- mean(listing$price,na.rm = TRUE)
1.3.1使用均值代替缺失值
listing$price_new <- ifelse(is.na(listing$price)== TRUE,price_mean,listing$price)# 新建一列变量price_new,如果是缺失值就用均值替代
summary(listing)
1.3.2.使用前一个数据代替缺失值
1.3.3.使用后一个数据代替缺失值
2. 异常值
2.1 基于统计分布检验和去除异常值(x的值如果在μ±3s范围外的数据均为异常值)
x_3s <- sqrt(var(listing$price_new))*3
x <- mean(listing$price_new)
x_up <- x+x_3s
x_down <- x-x_3s
listing2 <- listing[which(listing$price_new>x_down & listing$price_new < x_up),]
2.2 基于箱线图去除异常值(x的值从上下四分位数开始,超出1.5倍内距的值,均为异常值)
box_result <- boxplot.stats(listing$price_new)
price_min <- box_result$stats[1]
price_max <- box_result$stats[5]
listing3 <- listing[which(listing$price_new>=price_min & listing$price_new<=price_max),]
3 删除重复数据duplicated(需要不重复的列名)
listing4 <- listing[!duplicated(listing$room_type),]
时间序列数据处理
1. 日期时间格式转换
Sys.Date() # 输出当前日期 "2020-07-30",返回的是日期格式值
Sys.time() # 输出当前日期和时间 "2020-07-30 16:05:26 CST",返回的是日期格式值
date() # 显示当前周几、月份、日、时间、年份,但是不是日期格式的数据,是字符串
is.Date(date()) # lubridate包的方法,可以看出,date()返回的是字符串,不是日期格式的数据
time1 <- as.POSIXlt('2020-07-30 15:33:00') #将标准日期格式的字符串转变为标准时间格式数据
time2 <- as.POSIXct('2020-07-30 15:33:00') # 以秒存储时间
unclass(time2)
time3 <- as.Date('2020-07-30 15:33:00') # 只有年月日
unclass(time3) # 返回从1970-01-01到time3的天数,1970-01-01作为0。(可以用作计算两个日期之间相差多少天)
2.输出具体日期年、月、周、季度
weekdays(time1) # 输出星期几
months(time1) # 输出几月
quarters(time1) # 输出第几季度
library(lubridate) #lubridate日期函数包,传入的值可以不是日期格式,但是形式要是日期形式,自带包的必须传日期格式的数据
year(time1) # 自带包里没有year函数,只有在lubridate包里面才有
weekdays(time1) # 输出星期几
months(time1) # 输出几月
quarters(time1) # 输出第几季度
day(time1) #输出当月的第几天
3. format函数提取关键信息
a <- Sys.time()
format(a,'%y-%b') # %d月份中的天数、%m月份(以数字形式)、%b月份(小写数字)、%B月份完整的月份(中文)、%y年份(只显示后两位)、%Y年份(全年份)
第三章 表、图
表
1. 频数分布表
table(listings$room_type)
prop.table(table(listings$room_type))
2. 列联表
table(listings$neighbourhood,listings$room_type)
prop.table(table(listings$neighbourhood,listings$room_type),1)*100
prop.table(table(listings$neighbourhood,listings$room_type),2)*100
图
1. 所有的图都有以下参数
主标题main = NULL, 副标题sub = NULL, X轴标题xlab = NULL, Y轴标题ylab = NULL,
2. 柱状图
barplot(table(listings$room_type),horiz = T) # horiz 默认FALSE,表示柱子垂直,TRUE表示柱子水平
barplot(table(listings$neighbourhood,listings$room_type))
barplot(table(listings$room_type,listings$neighbourhood),horiz = T)
3. 饼图
pie(table(listings$room_type))
pie(table(listings$neighbourhood,listings$room_type))
4. 直方图与核密度曲线
hist(listings$price,freq = F)
lines(density(listings$price),col='red') #核密度曲线
5.箱线图 ---1.5倍内矩外的点就叫做离群点,可以剔除,在图中就是原点的形式
boxplot(listings$price)
boxplot(listings$price~listings$room_type)
boxplot(listings$price~listings$neighbourhood)
boxplot.stats(listings$price) # 返回list,list$stats返回数据的四分位点及修正后的极值,list$n返回观测值个数,list$conf返回中位数的置信区间,list$out返回箱线图超过极值的离群点
boxplot.matrix(listings$price)
6. 散点图
listings$new_price<-listings$price^2/2300
plot(listings$price,listings$new_price)
7.图形美化
c<-c(2,3,4,5,6,7)
d<-c(2,3,4,5,6,7)
a<-c(1,2,3,4,5,6)
opar<-par(no.readonly = TRUE) # 生成一个可以修改的当前图形参数列表
par(mfrow=c(1,2)) # 生成1行2列的画布
par(pin=c(2,3)) # 图形的宽,高
par(lwd=2,cex=1.5) # 图形中先的宽度2,点的大小1.5
par(cex.axis=0.75,font.axis=3) # 字体大小0.75,字体类型3号
plot(a,c,type='b',pch=19,lty =2,col='red') #a,c点点图,有点有趋势线,点类型19,线类型2(虚线),线颜色红色
plot(a,d,type='b',pch=23,lty=6,col='blue',bg='green') # a,d点图,有点有趋势线,点类型23,线类型6,线颜色蓝色,背景颜色绿色
par(opar) # 结束该图表参数列表
https://www.jianshu.com/p/f4fd994b50e0
使用ggplot2包实现画图
library(ggplot2)
listings$newtype<-as.factor(listings$room_type)
1. 散点图
ggplot(listings,aes(x=price,y=new_price))+geom_point(pch=17,size=2,col='red')+geom_smooth(method = 'lm',linetype=2,fullrange=F)+labs(title = '散点图',x='price',y='newprice')
ggplot(listings,aes(x=price,y=new_price))+geom_point()+geom_hline(yintercept = 1000) # 水平线
ggplot(listings,aes(x=price,y=new_price))+geom_point()+geom_vline(xintercept = 1000) # 垂直线
ggplot(listings,aes(x=price,y=new_price))+geom_point()+geom_line() # 连接各点
2. 柱状图
ggplot(listings,aes(x=neighbourhood))+geom_bar()
3.箱线图
ggplot(listings,aes(y=price))+geom_boxplot() # 垂直的箱线图
ggplot(listings,aes(x=price))+geom_boxplot() # 水平的箱线图
ggplot(listings,aes(x=newtype,y=price))+geom_boxplot() # price针对roomtype分组的箱线图
4. 直方图和核密度曲线
ggplot(listings,aes(x=price))+geom_histogram() #直方图频数分布
ggplot(listings,aes(x=price))+geom_histogram(aes(y=..density..))+geom_density() # 直方图频率分布及核密度曲线
5.折线图
ggplot(listings,aes(x=price,y=new_price))+geom_point()+geom_line() # 连接各点
第四章 统计数值描述分析
自带包
summary(listings) # 数值型数据会把最大值,最小值,均值中位数和四分位数给出,分类型变量会给出数量
summary(listing) # NA's就是缺失值数
Hmisc包的describe() 没有数量的限制,对因子型变量有统计各水平的频次和频率。
library(Hmisc)
describe(listings)
pastecs包的stat.desc函数 数量在3-5000条-------不推荐使用
library(pastecs)
listings_4999<-listings[1:4999,]
stat.desc(listings_4999$price,norm = T)
psych包中describe()-------------推荐使用
(mad: 绝对中位差;trimmed:切尾均值,切尾比例为0.1)
library(psych)
describe(listings)
describe(listings$price)
第五章 参数估计
点估计—总体均值和总体方差的点估计
summary(listings)
mean(listings$price,na.rm = TRUE) # 一个总体的均值点估计
var(listings$price,na.rm = T) # 一个总体的方差点估计
区间估计—总体均值的
1.计算区间估计上下限
t.test(listings$price,conf.level = 0.99) # 置信水平conf.level默认为0.95
2.绘制箱线图和直方图,观察分布情况,是否符合正态分布
p<-par(no.readonly = TRUE)
par(mfrow=c(1,2))
hist(listings$price,freq = F)
lines(density(listings$price),col='red')
boxplot(listings$price)
par(p)
3.绘制QQ图检验是否服从正态分布
qqnorm(listings$price);qqline(listings$price)
区间估计—总体方差的
R没有自带的计算方差的包,这里编写chisq.var.test函数来计算
chisq.var.test<-function(x,var,alpha=0.05,alternative='two.sided'){
options(digits = 4)
result<-list()
n<-length(x)
v<-var(x)
result$var<-v
chi2<-(n-1)*v/var
result$chi2<-chi2
p<-pchisq(chi2,n-1)
if(alternative =='less'|alternative=='greater'){result$p.value<-p}else if(alternative=='two.sided'){if(p>0.5)p<-1-p
p<-2*p
result$p.value<-p}else return('your input is wrong')
result$conf.int<-c((n-1)*v/qchisq(alpha/2,df=n-1,lower.tail = F),(n-1)*v/qchisq(alpha/2,df=n-1,lower.tail = T))
result
}
chisq.var.test(listings$price,var(listings$price),0.05)
第六章 假设检验
总体均值的假设检验
单样本T检验
1. 双尾:
t.test(listings$price,mu=400) # conf.level(置信水平)默认0.95
2.单尾:
商业数据分析上看,一般单尾的p值是双尾p值的一半,所以,一般双尾的结果拒绝,那么单尾的结果也会拒绝,所以一般商业数据分析的时候都不做单尾,只做双尾检验。
t.test(listings$price,mu=400,alternative = 'greater') # alternative参数代表备择下设,如果是greater则是右尾,less则是左尾,two.sided(默认)即双尾
两样本T检验
listings$newtype<-ifelse(listings$room_type=='Entire home/apt','Entire home/apt','other')
1.方差齐性检验--两个总体方差是否相同
var.test(listings$price~listings$newtype) # 方差齐性检验结果,原假设:两样本方差相同,备择假设:两样本方差不同。
2.两样本T检验--原假设:两样本均值相同,备择假设:两样本均值不同
2.1两样本方差不同
t.test(listings$price~listings$newtype,var.equal=F) # var.equal默认为FALSE,所以如果是方差非齐性的可以直接省略
2.2两样本方差相同
t.test(listings$price~listings$newtype,var.equal=T)
总体成数的假设检验
单样本
(研究Entire home/apt占比的单样本总体成数检验)
listings$newtype <- as.factor(listings$newtype)
a <- summary(listings$newtype)
prop.table(table(listings$newtype))
b <- length(listings$newtype)
prop.test(a[1],b,p = 0.5,alternative = 'two.sided') # 默认P=0.5,a[1]是成功的次数,b是总的次数,得到结果可以看出,总体成数明显不等于0.5,拒绝原假设,区间估计范围是0.6021214 0.6169395
两样本
(研究东城区和西城区的Entire home/apt方形占比是否相同)
table(listings$neighbourhood,listings$newtype) # 得到,东城区Entire home/apt房型1641个,总共2363套房子,西城区691套Entire home/apt,总共1094套房子
x <- c(1641,691)
n <- c(2363,1094)
prop.test(x,n,alternative = 'two.sided')
总体方差的假设检验
单样本(R没有自带包的假设检验,需要自带函数)
univariate.var.test = function(x,var,mu=Inf,alternative="two.sided"){
n=length(x)
df=n-1 #均值未知时的自由度
var.est=var(x) #均值未知时的方差估计值
if(mu<Inf){df=n;var.est=sum((x-mu)^2)/n}# 总体均值已知的情况
chi2=df*var.est/var.est
options(digits = 3)
return(data.frame(Pop.var=var,Samp.var=var.est,df=df,Chi2.stat=chi2,P=2*min(pchisq(chi2,df),pchisq(chi2,df,lower.tail=F))))
if(alternative=="greater")result$P=pchisq(chi2,df,lower.tail = F)
else if(alternative=="less")result$P=pchisq(chi2,df)
result
}
e <- univariate.var.test(listings$price,var(listings$price))
e
两样本
var.test(listings$price~listings$newtype)
第七章 卡方检验
自带包卡方检验
chisq.test(listings$newtype,listings$room_type)
原假设:两个分组型变量之间没有关系,备择假设:两个分组型变量有明显的关系
如果p值远小于0.05那么就说明拒绝原假设,说明两个分组型变量间相关性很大
prettyR包中的xtab()进行卡方检验
library(prettyR)
xtab(~newtype+room_type,data=listings)
第八章 方差分析
单因素方差分析
1.将分组型变量转变成因子数据
is.factor(listings$room_type)
listings$new_roomtype <- as.factor(listings$room_type)
is.factor(listings$new_roomtype)
2.按因子分水平查看各水平数据情况
tapply(listings$price,listings$new_roomtype,summary)
# 按因子分水平查看各水平数据情况,发现各水平均值都不同
3.进行单因素方差分析
anova(lm(listings$price~listings$new_roomtype))
# 结果P值如果小于0.05则说明该因子对price有显著的影响
4.多重比较(LSD检验)—基于agricolae包
library(agricolae)
model <-aov(price~new_roomtype,data=listings)
model
out <- LSD.test(model,'new_roomtype',p.adj = 'none')
out
多因素方差分析
(一般在探索数据分析中,会将每个变量的交互项都进行分析下,如果没有通过检验,则去除掉交互项再进行无交互项的方差分析)
本例中用room_type和neighbourhood两个变量组进行双因素方差分析
listings$neighbourhood_new<-as.factor(listings$neighbourhood) # 将行政区变量转变成因子变量
无交互项的多因素方差分析
anova(lm(listings$price~listings$new_roomtype+listings$neighbourhood_new))
有交互项的多因素方差分析
anova(lm(listings$price~listings$new_roomtype+listings$neighbourhood_new+listings$new_roomtype*listings$neighbourhood_new))
双因素方差分析的LSD多重比较
library(agricolae)
model <-aov(price~new_roomtype+neighbourhood_new,data=listings)
model
out <- LSD.test(model,c('new_roomtype','neighbourhood_new'),p.adj = 'none')
out
第九章 相关和回归
相关性分析
1.散点图
plot(listings$price,listings$new_price) +
library(ggplot2)
ggplot(listings, aes(x = price, y = new_price)) + geom_point() + geom_smooth(method = "lm") + labs(x = "横坐标标题", y = "纵坐标标题")
ggplot(listings, aes(x = price, y = sqrt(new_price))) + geom_point() + geom_smooth(method = "lm") + labs(x = "横坐标标题", y = "纵坐标标题")
2.计算相关系数(pearson相关系数来看线性相关程度,spearman相关系数来看非线性相关程度)
cor(listings$price,listings$new_price)
cor(listings$price,listings$new_price,method = 'spearman')
3. 相关性的显著性检验
cor.test(listings$price,listings$new_price) # 默认method是pearson相关系数
cor.test(listings$price,listings$new_price,method = 'spearman')
回归分析
简单线性回归(一元线性回归)
1. 先做了相关分析;
2. 计算回归参数及回归方程:
listings<-na.omit(listing)
result<-lm(listings$price~listings$new_price)
summary(lresult)
3. 点预测及计算残差
listings$predict1<-predict(result)
listings$fitted<-fitted(lresult)
listings$resid<-resid(result)
predict和fitted都是点估计的预测方法,计算结果相同
残差项用于后面对残差进行分析
4. 区间预测(result为回归后的结果)
预测区间:result.pred <- predict(result,interval="prediction",level=0.95)
置信区间:result.pred <- predict(result,interval="confidence",level=0.95)
结果:
![简单线性回归结果](https://img-blog.csdnimg.cn/20200630165702565.png?x-oss-
process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zOTEyNzgxMA==,size_16,color_FFFFFF,t_70)
从结果可以看出,总体回归方程的R方是0.86,解释性较好,F检验拒绝原假设,各系数的T检验也拒绝了原假设,说明两个变量之间存在很强的相关性,并且回归方程拟合较好。
回归方程为 price=1.329new_price+0.02685