龙猫芭蕉

读万卷书,行万里路

  • 主页
  • 随笔
  • 笔记
所有文章 关于我

龙猫芭蕉

读万卷书,行万里路

  • 主页
  • 随笔
  • 笔记

ggplot2与数据操作

2020-04-08
字数统计: 3.2k字   |   阅读时长: 15分

1 一些好用的R包

1.1 plyr包

plyr包提供了一整套工具集来处理列表、数组和数据框,把复杂的数据分割成几个部分,用某个函数分别对各个部分进行处理,最后把这些结果综合到一起。主要函数是ddply()函数:ddply(data, .(var1, var2), fun, ...)

需要用到的统计汇总函数:
subset()对数据取子集
transform()进行数据变换,计算分组统计量(如各组的标准差),并且加到原数据上去。
colwise()用来向量化一个普通函数,即能把原本只接受向量输入的函数变成可以接受数据框输入的函数,它返回的是一个新的函数。相应的,numcolwise()只对数值类型的列操作,catcolwise()只对分类类型的列操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
> library(plyr)
#subset():选取各个颜色里最小的钻石
> ddply(diamonds, .(color), subset, carat == min(carat))
#transform():把每个颜色组里钻石的价格标准化,使其均值为0,方差为1
> ddply(diamonds, .(color), transform, price = scale(price))
#colwise()向量化函数
> nmissing <- function(x) sum(is.na(x))
> nmissing(msleep$brainwt)
[1] 27
> colwise(nmissing)(msleep)
name genus vore order conservation sleep_total sleep_rem sleep_cycle awake
1 0 0 7 0 29 0 22 51 0
brainwt bodywt
1 27 0
#numcolwise()函数与ddply()一起对数据进行分组统计
> ddply(msleep, .(vore), numcolwise(median), na.rm = T)
vore sleep_total sleep_rem sleep_cycle awake brainwt bodywt
1 carni 10.4 1.95 0.3833333 13.6 0.044500 20.490
2 herbi 10.3 0.95 0.2166667 13.7 0.012285 1.225
3 insecti 18.1 3.00 0.1666667 5.9 0.001200 0.075
4 omni 9.9 1.85 0.5000000 14.1 0.006600 0.950
5 <NA> 10.6 2.00 0.1833333 13.4 0.003000 0.122

1.2 dplyr包

filter()筛选行,逻辑运算有一个简写x %in% y,用于选取出x 是y 中的一个值时的所有行。
arrange()排列行,使用desc()可以按列进行降序排列。
select()选择列,可以使用starts_with()、contains()、everything()等辅助函数。
mutate()添加新变量,如果只想保留新变量,可以使用transmute()函数。
summarize()进行分组摘要,经常和group_by()函数联合起来使用,其可以改变函数的作用范围,使得从在整个数据集上操作变为在每个分组上分别操作。
管道操作:%>%,可以读作“然后”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
> library(dplyr)
> library(nycflights13)
> filter(flights, month == 11 | month == 12)
# A tibble: 55,403 x 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 11 1 5 2359 6 352 345
2 2013 11 1 35 2250 105 123 2356
3 2013 11 1 455 500 -5 641 651
4 2013 11 1 539 545 -6 856 827
5 2013 11 1 542 545 -3 831 855
6 2013 11 1 549 600 -11 912 923
7 2013 11 1 550 600 -10 705 659
8 2013 11 1 554 600 -6 659 701
9 2013 11 1 554 600 -6 826 827
10 2013 11 1 554 600 -6 749 751
# ... with 55,393 more rows, and 11 more variables: arr_delay <dbl>,
# carrier <chr>, flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
# air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
#上面语句还可以表示为:
> nov_dec <- filter(flights, month %in% c(11, 12))
#根据arr_delay列队数据集进行降序排列
> arrange(flights, desc(arr_delay))
#选择flights数据集中的year, month和day列
> select(flights, year, month, day)
#和everything()使用,将几个变量移到数据框开头
> select(flights, time_hour, air_time, everything())
#添加新变量
> mutate(flights,
+ gain = arr_delay - dep_delay,
+ speed = distance / air_time * 60
+ )
#summarize()进行分组摘要
> by_day <- group_by(flights, year, month, day)
> summarize(by_day, delay = mean(dep_delay, na.rm = TRUE))
# A tibble: 365 x 4
# Groups: year, month [12]
year month day delay
<int> <int> <int> <dbl>
1 2013 1 1 11.5
2 2013 1 2 13.9
3 2013 1 3 11.0
4 2013 1 4 8.95
5 2013 1 5 5.73
6 2013 1 6 7.15
7 2013 1 7 5.42
8 2013 1 8 2.55
9 2013 1 9 2.28
10 2013 1 10 2.84
# ... with 355 more rows
#管道操作
> (delays <- flights %>%
+ group_by(dest) %>%
+ summarize(count = n(),
+ dist = mean(distance, na.rm = TRUE),
+ delay = mean(arr_delay, na.rm = TRUE)) %>%
+ filter(count > 20, dest != 'HNL'))
# A tibble: 96 x 4
dest count dist delay
<chr> <int> <dbl> <dbl>
1 ABQ 254 1826 4.38
2 ACK 265 199 4.85
3 ALB 439 143 14.4
4 ATL 17215 757. 11.3
5 AUS 2439 1514. 6.02
6 AVL 275 584. 8.00
7 BDL 443 116 7.05
8 BGR 375 378 8.03
9 BHM 297 866. 16.9
10 BNA 6333 758. 11.8
# ... with 86 more rows

常用的摘要函数

分散程度度量:sd(x)、IQR(x)、mad(x)
秩的度量:min(x)、quantile(x, 0.25)、max(x)
排秩:min_rank(x)将最小值排在最前面,使用min_rank(desc(x))可以让最大值排在最前面
定位度量:first(x)、nth(x, 2)、last(x)
计数:n()不需要任何参数,返回当前分组的大小;sum(!is.na(x))计算非缺失值的数量;n_distinct(x)计算出唯一值的数量;count(x, wt = y)可以选择加权变量y对x进行计数。
逻辑值的计数和比例:sum(x > 10)和mean(y == 0)

2 向量化操作

sapply()可以输入向量、数据框和列表,对其以输入的函数进行向量化计算;
lapply()也和sapply()函数一样,区别在于返回结果的形式是一个列表。如果想将该结果转换为一个整齐的矩阵,有三种方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
> myfunc <- function(x) {
+ ret <- c(mean(x), sd(x))
+ return(ret)
+ }
> mylist <- as.list(iris[, 1:4])
> result <- lapply(mylist, myfunc)
> result
$Sepal.Length
[1] 5.8433333 0.8280661

$Sepal.Width
[1] 3.0573333 0.4358663

$Petal.Length
[1] 3.758000 1.765298

$Petal.Width
[1] 1.1993333 0.7622377

> t(as.data.frame(result))
[,1] [,2]
Sepal.Length 5.843333 0.8280661
Sepal.Width 3.057333 0.4358663
Petal.Length 3.758000 1.7652982
Petal.Width 1.199333 0.7622377
#还可以:
> t(sapply(result, '['))
#或者:
> do.call('rbind', result)

apply()和sapply()函数一样,只是其中多了一个参数MARGIN,其值为1,表示以行为计算单位,其值为2,表示以列为计算单位。
tapply()按变量的取值进行划分。第一个参数是计算的对象,第二个参数是划分数据的依据,第三个参数是计算所用的函数。
aggregate()和tapply()函数类似,不过前者的功能略强于后者,而且以数据框形式输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
> set.seed(1)
> vec <- round(runif(12)*100)
> mat <- matrix(vec, 3, 4)
> apply(mat, MARGIN = 1, sum)
[1] 218 144 228
> apply(mat, MARGIN = 2, function(x) max(x)-min(x))
[1] 30 71 31 15

> tapply(X = iris$Sepal.Length, INDEX = list(iris$Species), FUN = mean)
setosa versicolor virginica
5.006 5.936 6.588

> with(iris, aggregate(Sepal.Length, by = list(Species), mean))
Group.1 x
1 setosa 5.006
2 versicolor 5.936
3 virginica 6.588

mapply()用于两个参数同时需要变化的情况,如计算九九乘法表,是sapply()的增强版,可以处理3个及以上参数的向量化计算问题。
outer():如果只处理两个参数,outer()也比较方便。
replicate()能让某个函数重复调用多遍,在统计模拟中非常有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
> vec1 <- vec2 <- 1:9
> para <- expand.grid(vec1, vec2) #将两个向量中的值两两配对
> res <- mapply(FUN = prod, para[, 1], para[, 2])
> res
[1] 1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21
[26] 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 45 6 12 18 24 30
[51] 36 42 48 54 7 14 21 28 35 42 49 56 63 8 16 24 32 40 48 56 64 72 9 18 27
[76] 36 45 54 63 72 81
> myfunc <- function(x, y){
+ left <- paste0(x, '*', y, '=')
+ right <- x*y
+ ret <- paste0(left, right)
+ return(ret)
+ }
> outer(vec1, vec2, FUN = myfunc)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] "1*1=1" "1*2=2" "1*3=3" "1*4=4" "1*5=5" "1*6=6" "1*7=7" "1*8=8"
[2,] "2*1=2" "2*2=4" "2*3=6" "2*4=8" "2*5=10" "2*6=12" "2*7=14" "2*8=16"
[3,] "3*1=3" "3*2=6" "3*3=9" "3*4=12" "3*5=15" "3*6=18" "3*7=21" "3*8=24"
[4,] "4*1=4" "4*2=8" "4*3=12" "4*4=16" "4*5=20" "4*6=24" "4*7=28" "4*8=32"
[5,] "5*1=5" "5*2=10" "5*3=15" "5*4=20" "5*5=25" "5*6=30" "5*7=35" "5*8=40"
[6,] "6*1=6" "6*2=12" "6*3=18" "6*4=24" "6*5=30" "6*6=36" "6*7=42" "6*8=48"
[7,] "7*1=7" "7*2=14" "7*3=21" "7*4=28" "7*5=35" "7*6=42" "7*7=49" "7*8=56"
[8,] "8*1=8" "8*2=16" "8*3=24" "8*4=32" "8*5=40" "8*6=48" "8*7=56" "8*8=64"
[9,] "9*1=9" "9*2=18" "9*3=27" "9*4=36" "9*5=45" "9*6=54" "9*7=63" "9*8=72"
#这里省略[,9]
#先生成10000 个服从正态分布的随机向量,然后计算其均值,用replicate()使这个过程重复100 遍。
> res2 <- replicate(100, mean(rnorm(10000)))

3 数据转换整理

3.1 长宽格式互转

宽型数据:各变量取值类型一致,而变量以不同列的形式构成,又称为非堆叠数据。
长型数据:各变量取值在一列,而对应的变量名在另一列。又称为堆叠数据,只要在一列中存在分类变量,都可以将其看做是长型数据。
两种数据可以通过stack()和unstack()进行互相转换,然后计算分析结果。

如果想一步直接得到分析结果,可以使用更为强大的reshape2包:
dcast()作用是将长型数据进行汇总计算,思路与aggregate()和plyr包的ddply()函数很相似。这些函数使用的前提是,数据中已经存在分类变量,根据分类变量划分数据,再计算某个数值变量。其中,aggregate是最弱的,只能按单个变量划分数据,计算单个数值对象;dcast要强一些,可以按多个变量划分数据,但也只能计算单个数值对象;ddply是最强的数据整理函数,它可以按多个变量划分数据,并计算整个数据框的所有变量,在自定义函数的配合下极为灵活。
melt()作用是将一个宽型数据融合成一个长型数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
> subdata <- iris[, 4:5]
> data_w <- unstack(subdata)
> head(data_w)
setosa versicolor virginica
1 0.2 1.4 2.5
2 0.2 1.5 1.9
3 0.2 1.5 2.1
4 0.2 1.3 1.8
5 0.2 1.5 2.2
6 0.4 1.3 2.1
> colMeans(data_w)
setosa versicolor virginica
0.246 1.326 2.026

> library(reshape2)
> dcast(subdata, Species~., value.var = 'Petal.Width', fun = mean)
Species .
1 setosa 0.246
2 versicolor 1.326
3 virginica 2.026
#用ddply()函数实现
> myfuns <- function(x){
+ mean(x$Sepal.Length)
+ }
> ddply(iris, 'Species', myfuns)
Species V1
1 setosa 5.006
2 versicolor 5.936
3 virginica 6.588

> iris_long <- melt(iris, id = 'Species')
> head(iris_long)
Species variable value
1 setosa Sepal.Length 5.1
2 setosa Sepal.Length 4.9
3 setosa Sepal.Length 4.7
4 setosa Sepal.Length 4.6
5 setosa Sepal.Length 5.0
6 setosa Sepal.Length 5.4
> dcast(iris_long, formula = Species~variable, value.var = 'value', fun = mean)
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

3.2 数据的拆分与合并

3.2.1 拆分

常规的数据分拆其实就是取子集,使用subset()函数即可完成。非常规一点的数据拆分是按照某个分类变量进行,可以用split()和unsplit()完成。

1
2
3
4
> iris_splited <- split(iris, f = iris$Species)
> class(iris_splited)
[1] "list"
> iris_all <- unsplit(iris_splited, f = iris$Species)

3.2.2 合并连接

merge()函数:

1
2
3
4
5
6
> datax <- data.frame(id = c(1, 2, 3), age = c(23, 34, 41))
> datay <- data.frame(id = c(1, 2, 4), name = c('Tom', 'John', 'Ken'))
> merge(datax, datay, by = 'id')
id age name
1 1 23 Tom
2 2 34 John

键的概念:用于连接每对数据表的变量,是能唯一标识观测的变量(或变量集合)。有两种类型:
主键:唯一标识其所在数据表中的观测。
外键:唯一标识另一个数据表中的观测。

根据dplyr包中的函数,连接也可以分为:
内连接:inner_join(),保留同时存在于两个表中的观测,容易丢失观测
外连接:保留至少存在于一个表中的观测,有三种类型:
-左连接:left_join(),保留x中的所有观测,最常用
-右连接:right_join()保留y中的所有观测
-全连接:full_join()保留x和y中的所有观测


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
> inner_join(datax, datay, by = 'id')
id age name
1 1 23 Tom
2 2 34 John
> left_join(datax, datay, by = 'id')
id age name
1 1 23 Tom
2 2 34 John
3 3 41 <NA>
> right_join(datax, datay, by = 'id')
id age name
1 1 23 Tom
2 2 34 John
3 4 NA Ken
> full_join(datax, datay, by = 'id')
id age name
1 1 23 Tom
2 2 34 John
3 3 41 <NA>
4 4 NA Ken

merge()、dplyr连接操作与SQL三者之间的联系:

  • 本笔记参考书目:Hadley Wickham的《ggplot2:数据分析与图形艺术》、Hadley Wickham &
    Garrett Grolemund的《R数据科学》以及李舰&肖凯的《数据科学中的r语言》
赏

谢谢你请我吃糖果

微信
  • 笔记
  • R语言
  • ggplot2

扫一扫,分享到微信

微信分享二维码
函数、判断与迭代
ggplot2学习笔记(2)
© 2021 龙猫芭蕉
Hexo Theme Yilia by Litten
  • 所有文章
  • 关于我

tag:

  • 随笔
  • 笔记
  • 数据分析与挖掘
  • 机器学习
  • R语言
  • 数据分析
  • SQL
  • Python
  • Hexo
  • ggplot2
  • 读后感
  • 爬虫
  • vlog
  • 生活记录

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • 告别2020

    2021-01-01

    #随笔

  • 数模回忆录

    2020-11-26

    #随笔

  • 立冬 | 南国之冬

    2020-11-07

    #vlog#生活记录

  • 请抵达安宁吧

    2020-08-30

    #随笔

  • 爬虫案例 | 基于lxml和Beautiful Soup解析器

    2020-08-29

    #笔记#Python#爬虫

  • 美食记忆 | 广式早茶

    2020-08-22

    #随笔

  • 南沙印象 | 走走停停的周末

    2020-08-16

    #随笔

  • 小向往

    2020-08-08

    #随笔

  • MySQL整理之DQL语言的学习

    2020-05-20

    #笔记#数据分析#SQL

  • MySQL整理

    2020-05-17

    #笔记#数据分析#SQL

  • Pandas整理

    2020-05-01

    #笔记#数据分析#Python

  • NumPy整理

    2020-04-28

    #笔记#数据分析#Python

  • 鸡零狗碎

    2020-04-27

    #随笔

  • 使用stringr处理字符串

    2020-04-20

    #笔记#R语言

  • 函数、判断与迭代

    2020-04-17

    #笔记#R语言

  • ggplot2与数据操作

    2020-04-08

    #笔记#R语言#ggplot2

  • ggplot2学习笔记(2)

    2020-03-31

    #笔记#R语言#ggplot2

  • ggplot2学习笔记(1)

    2020-03-31

    #笔记#R语言#ggplot2

  • 就是这样了

    2020-03-29

    #随笔#读后感

  • R语言数据挖掘——图形交互界面Rattle的安装与使用

    2020-03-26

    #笔记#数据分析与挖掘#机器学习#R语言

  • R语言数据挖掘——支持向量机

    2020-03-24

    #笔记#数据分析与挖掘#机器学习#R语言

  • R语言数据挖掘——随机森林

    2020-03-23

    #笔记#数据分析与挖掘#机器学习#R语言

  • R语言数据挖掘——集成学习

    2020-03-22

    #笔记#数据分析与挖掘#机器学习#R语言

  • R语言数据挖掘——决策树

    2020-03-21

    #笔记#数据分析与挖掘#机器学习#R语言

  • R语言数据挖掘——判别分析

    2020-03-19

    #笔记#数据分析与挖掘#机器学习#R语言

  • R语言数据挖掘——聚类分析

    2020-03-15

    #笔记#数据分析与挖掘#机器学习#R语言

  • R语言数据挖掘——关联分析

    2020-03-14

    #笔记#数据分析与挖掘#机器学习#R语言

  • 我的寒假

    2020-03-07

    #随笔

  • DBSCAN与层次聚类

    2020-02-29

    #笔记#数据分析与挖掘#机器学习#Python

  • Kmeans聚类分析

    2020-02-27

    #笔记#数据分析与挖掘#机器学习#Python

  • 朴素贝叶斯模型

    2020-02-25

    #笔记#数据分析与挖掘#机器学习#Python

  • KNN模型

    2020-02-22

    #笔记#数据分析与挖掘#机器学习#Python

  • 决策树与随机森林

    2020-02-21

    #笔记#数据分析与挖掘#机器学习#Python

  • Logistic回归分类模型

    2020-02-19

    #笔记#数据分析与挖掘#机器学习#Python

  • 岭回归与LASSO回归模型

    2020-02-17

    #笔记#数据分析与挖掘#机器学习#Python

  • 线性回归预测模型

    2020-02-15

    #笔记#数据分析与挖掘#机器学习#Python

  • sql简单语句整理

    2020-02-12

    #笔记#数据分析#SQL

  • 告别2019

    2019-12-31

    #随笔

  • 光影碎片

    2019-12-20

    #随笔

  • 艰辛的hexo之路:gitalk评论插件踩过的坑

    2019-12-11

    #随笔#Hexo

愿一生

温暖纯良
不舍爱与自由