R语言数据的排序、转换、汇总

本系列为R语言系统学习笔记,已收录至“R语言笔记”专栏,可戳右下角专栏目录订阅,空余时间会持续更新。往期文章:
0. R的下载与安装 vs Rstudio报错
1. R语言向量、矩阵、数组、数据框
2. R语言条件、循环、函数
3. R语言数据的读取与导出

数据排序

sort函数

x <- sample(1:100,10)
sort(x, decreasing = T) #默认是从小到大排序
y <- c('python','ruby','java','r')
sort(y,decreasing = T) #[1] "ruby" "r" "python" "java"  

rank函数

rank(x) #秩次排序,生成变量的秩次排名
z <- c(1,2,3,3,4,4,5,6,6,6,7,8,8)
rank(z) #结果出现了小数,当rank识别到相同的元素,会取元素秩次均值

order函数

x #[1] 39 97 31 83 56  1 19 60 50 41
order(x) #[1]  6  7  3  1 10  9  5  8  4  2 返回的是元素下标
x[order(x)] #下标再传入x即可生成排序 [1]  1 19 31 39 41 50 56 60 83 97
head(iris)
head(iris[order(iris$Sepal.Length,decreasing = T),]) #按Sepal.Length列从大到小的顺序排列
head(iris[order(-iris$Sepal.Length),]) #加负号也可按从大到小的顺序排列
#对多个变量进行排序
head(iris[order(iris$Sepal.Length, iris$Sepal.Width),]) #先对Sepal.Length排序(从小到大),在此基础上对Sepal.Width排序

数据转换

长宽型数据转换

stack函数

freshmen <- c(178,180,182,180)
sophomores <- c(188,172,175,172)
juniors <- c(167,172,177,174)
data.frame(fr = freshmen, so = sophomores, ju = juniors) #结果如下
#结果如下,此时是宽型数据
'''
   fr  so  ju
1 178 188 167
2 180 172 172
3 182 175 177
4 180 172 174
'''
height <- stack(list(fresh = freshmen, sopho = sophomores, jun = juniors))
height #运用stack函数,将原本的数据堆栈为长型数据
#结果如下
'''
   values   ind
1     178 fresh
2     180 fresh
3     182 fresh
4     180 fresh
5     172 fresh
6     188 sopho
7     172 sopho
8     175 sopho
9     172 sopho
10    167   jun
11    172   jun
12    177   jun
13    174   jun
'''

tapply函数

tapply(height$values, height$ind, mean) #转换为长型数据后,可直接用tapply函数求各自统计量
#用tapply求统计量
'''
fresh  sopho    jun 
178.40 176.75 172.50 
'''

reshape函数

View(Indometh) #Indometh是一个长型数据
summary(Indometh) #输出Indometh的描述统计量
wide <- reshape(Indometh, v.names = 'conc', idvar = 'Subject', timevar = 'time', direction = 'wide')
#v.names将哪个变量作为value,idvar指标识变量是哪个,timevar作为列
View(wide)
long <- reshape(wide, v.names = 'conc', idvar = 'Subject', varying = list(2:12), direction = 'long')
#varying = list(2:12)将2到12列堆栈到一起 
View(long)

reshape2函数

  • 加载reshape2包
install.packages("reshape2")
library(reshape2) #常用melt()融化函数和dcast()汇总操作函数
  • 使用melt函数
new_iris <- melt(data = iris, di.var = 'Species') #将Species列作为标识列,其它的堆起来(长型)
View(new_iris)
levels(new_iris$variable)
  • 计算指标均值
dcast(new_iris, formula = Species~variable, fun.aggregate = mean, value.var = 'value') #计算指标的均值
#结果
'''
     Species Sepal.Length Sepal.Width Petal.Length Petal.Width
1     setosa        5.006       3.428        1.462       0.246
2 versicolor        5.936       2.770        4.260       1.326
3  virginica        6.588       2.974        5.552       2.026
'''
  • 实例:小费tips数据集
dcast(data = tips, formula = sex~.,fun.aggregate = mean, value.var = 'tip')
#结果
'''
sex        .
1 Female 2.833448
2   Male 3.089618
'''
dcast(data = tips, formula = sex~smoker, fun.aggregate = mean, value.var = 'tip')
#性别sex、不抽烟No、抽烟Yes
'''
     sex       No      Yes
1 Female 2.773519 2.931515
2   Male 3.113402 3.051167
'''

变量因子化(连续变量离散化)

age <- sample(20:80, 20)
age
  • 方法一 (公式法,True=1,False=0)
age1 <- 1 + (age > 30) + (age >= 40) + (age >=50)
age_fac <- factor(age1, labels = c('young','middle','m-old','old'))
age_fac
age2 <- 1*(age < 30) + 2*(age >= 30 & age < 40) + 3*(age >= 40 & age < 50) + 4*(age > 50) 
  • 方法二(cut函数)
age3 <- cut(age, breaks = 4, labels = c('young','middle','m-old','old'), include.lowest = T, right = T)
#注意此时break = 4 是均匀的分4份,而不是之前的每20岁切一档
#include.lowest = T 设置为左闭区间,设置为右闭区间right = T
age4 <- cut(age, breaks = seq(20,80,len = 4), labels = c('young','middle','old'))
age4 #此时用seq函数在break中设置了20、40、60、80为年龄分段的函数
  • 方法三(if else)
ifelse(age > 50, 'old','young')
ifelse(age > 60, 'old', ifelse(age < 30, 'young','middle')) #同Excel中的if函数
  • 方法四(car)
install.packages('car')
library(car)
recode(var = age, recodes = 'lo:29 = 1; 30:39 = 2; 40:49 = 3; 50:hi = 4')

数据汇总

apply家族

apply函数

mat <- matrix(1:24, nrow = 4, ncol = 6)
apply(mat, 1, sum) #计算行和
#注释:第二个指标为margin,1代表行,2代表列
apply(mat, 1, mean) #计算每一行均值
apply(mat, 2, mean) #计算每一列均值
apply(iris[,1:4],2,mean) #计算iris中1:4列均值

lapply函数

lapply(X = c(1:5),FUN = log) #对X遍历,都返回log
lapply(iris[,1:3], function(x)lm(x~iris$Sepal.Width,data = iris[,1:3]))#iris数据集前三列与Sepal.Width列进行回归
  • lapply用于以list为结果返回的函数,适用于返回线性回归结果

sapply函数

sapply(1:5,log)
#返回向量、矩阵、数据框
sapply(1:5,function(x)x+3)

tapply函数

tapply(X = iris$Sepal.Length,INDEX = iris$Species, FUN = mean)#根据Species将Sepal.Length切分,分别计算均值
  • tapply只适用于数据框
tapply(iris[,1:4],INDEX = iris$Species, FUN = mean)
#此时报错×Error in tapply(iris[, 1:4], INDEX = iris$Species, FUN = mean) : 参数的长度必需相同
#可用上述dcast()函数
#根据分类变量将数值型变量进行切分,分类汇总

mapply函数

myfun <- function(x,y){
  if(x>4)return(y)
  else return(x+y)
}
myfun(1:5, 2:6)
#此时会报错:Error in if (x > 4) return(y) else return(x + y) : the condition has length > 1,因为if无法进行向量化操作
mapply(myfun, 1:5,2:6) #而使用mapply就具有向量化操作功能

ave函数

survival <- data.frame(id = 1:10, 
                       cancer = sample(c('lung','liver','colon'),10,replace = T),
                       treatment = sample(c('Surg','Chemo'),10,replace = T),
                       sur_days = sample(100:1000,10))
survival
ave(survival$sur_days,survival$cancer)#求不同分类水平(cancer)的(sur_days)均值
ave(survival$sur_days,survival$cancer,FUN = sd)#求不同分类水平(cancer)的(sur_days)标准差

by函数

by(data = survival$sur_days,INDICES = survival$cancer,FUN = mean)#求不同分类水平的均值(简洁)
by(data = survival$sur_days,INDICES = list(survival$cancer,survival$treatment),FUN = mean)

aggregate函数

data(mtcars)
View(mtcars)
aggregate(x = mtcars,by = list(VS = mtcars$vs==1, high = mtcars$mpg > 22),mean)
aggregate(x = mtcars[,1:4],by = list(VS = mtcars$vs==1, high = mtcars$mpg > 22),mean)
aggregate(iris,by = list(high_sp = iris$Sepal.Length>5,hige_sw = iris$Sepal.Width > 3.5),mean)
#字符串类会警告,数值型可直接求出
aggregate(.~Species,data = iris,mean)

by(mtcars,mtcars$cyl,function(x)lm(mpg~disp + hp, data = x))#自定义函数进行线性回归

sweep函数

#针对数组
my_array <- array(1:24, dim = c(3,4,2))
my_array
sweep(x = my_array, MARGIN = 1, STATS = 1, FUN = '+') #对于my_array每行元素+1
#MARGIN取行,默认是减法‘-’运算
  • cr.Leopard课程
  • 4
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值