R语言 Mutate家族


首先是加载相关的包,mutate主要属于dplyr包里,这里我们统一使用tidyverse包。
tidyverse包中含有各种数据整理以及画图的包,如下加载tidyverse包:

> library(tidyverse)
-- Attaching packages ------------------------ tidyverse 1.3.0 --
√ ggplot2 3.3.3     √ purrr   0.3.4
√ tibble  3.0.5     √ dplyr   1.0.3
√ tidyr   1.1.2     √ stringr 1.4.0
√ readr   1.4.0     √ forcats 0.5.1
-- Conflicts --------------------------- tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()

参考
https://dplyr.tidyverse.org/reference/mutate_all.html
教材《R数据科学》


mutate函数
mutate() 的主要功能是为数据框增加列。mutate总是把新的列加在数据集的最后。新列一旦创建就可以立即使用。
一个简单的栗子

> head(iris)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
#在最后的地方增加新列
> mutate(iris, new_col = Petal.Length + Petal.Width) %>% head()
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species new_col
1          5.1         3.5          1.4         0.2  setosa     1.6
2          4.9         3.0          1.4         0.2  setosa     1.6
3          4.7         3.2          1.3         0.2  setosa     1.5
4          4.6         3.1          1.5         0.2  setosa     1.7
5          5.0         3.6          1.4         0.2  setosa     1.6
6          5.4         3.9          1.7         0.4  setosa     2.1

PS:%>%是管道符号,用于把前面的数据向后传递,避免函数嵌套,增加代码的可阅读性。


mutate还有三个衍生函数:
mutate_at(); mutate_if(); mutate_all()
在官网上的关于这三个后缀的解释如下:
_all: affects every variable
_at: affects variables selected with a character vector or vars()
_if : affects variables selected with a predicate function:
其中,all是针对所有列,at是针对特定的列,if的满足特定条件的列
参数如下:
mutate_all(.tbl, .funs, ...)
mutate_if(.tbl, .predicate, .funs, ...)
mutate_at(.tbl, .vars, .funs, ..., .cols = NULL)

Arguments

image.png

解释一下官网给出的例子
mutate_at

scale2  <-  function(x, na.rm  =  FALSE)(x  -  mean(x, na.rm =  na.rm)) / sd(x, na.rm)
starwars  %>%  mutate_at(c("height", "mass"), scale2)
# A tibble: 87 x 14
   name    height  mass hair_color skin_color eye_color birth_year sex   gender
   <chr>    <dbl> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
 1 Luke S~     NA    NA blond      fair       blue            19   male  mascu~
 2 C-3PO       NA    NA NA         gold       yellow         112   none  mascu~
 3 R2-D2       NA    NA NA         white, bl~ red             33   none  mascu~
 4 Darth ~     NA    NA none       white      yellow          41.9 male  mascu~
 5 Leia O~     NA    NA brown      light      brown           19   fema~ femin~
 6 Owen L~     NA    NA brown, gr~ light      blue            52   male  mascu~
 7 Beru W~     NA    NA brown      light      blue            47   fema~ femin~
 8 R5-D4       NA    NA NA         white, red red             NA   none  mascu~
 9 Biggs ~     NA    NA black      light      brown           24   male  mascu~
10 Obi-Wa~     NA    NA auburn, w~ fair       blue-gray       57   male  mascu~
# ... with 77 more rows, and 5 more variables: homeworld <chr>, species <chr>,
#   films <list>, vehicles <list>, starships <list>

在height,mass列执行scale2
以下两个命令是等同的

starwars  %>% mutate_at(c(height,mass), scale2) 
starwars  %>% mutate(across(c("height", "mass"), scale2))

PS: across() 即让函数穿过所选择的列,即同时对所选择的多列应用若干函数,这里和mutate联合使用,达到mutate_at的作用。
mutate_at的参数中使用vars(), funs()来完善整个函数
eg:

> head(iris)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
> mutate_at(iris, vars(-Species), funs(log(.))) %>% head()
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1     1.629241    1.252763    0.3364722  -1.6094379  setosa
2     1.589235    1.098612    0.3364722  -1.6094379  setosa
3     1.547563    1.163151    0.2623643  -1.6094379  setosa
4     1.526056    1.131402    0.4054651  -1.6094379  setosa
5     1.609438    1.280934    0.3364722  -1.6094379  setosa
6     1.686399    1.360977    0.5306283  -0.9162907  setosa

mutate_if

starwars %>% mutate_if(is.numeric, scale2, na.rm = TRUE)
# A tibble: 87 x 14
   name        height    mass hair_color  skin_color eye_color birth_year sex  
   <chr>        <dbl>   <dbl> <chr>       <chr>      <chr>          <dbl> <chr>
 1 Luke Skyw~ -0.0678 -0.120  blond       fair       blue          -0.443 male 
 2 C-3PO      -0.212  -0.132  NA          gold       yellow         0.158 none 
 3 R2-D2      -2.25   -0.385  NA          white, bl~ red           -0.353 none 
 4 Darth Vad~  0.795   0.228  none        white      yellow        -0.295 male 
 5 Leia Orga~ -0.701  -0.285  brown       light      brown         -0.443 fema~
 6 Owen Lars   0.105   0.134  brown, grey light      blue          -0.230 male 
 7 Beru Whit~ -0.269  -0.132  brown       light      blue          -0.262 fema~
 8 R5-D4      -2.22   -0.385  NA          white, red red           NA     none 
 9 Biggs Dar~  0.249  -0.0786 black       light      brown         -0.411 male 
10 Obi-Wan K~  0.220  -0.120  auburn, wh~ fair       blue-gray     -0.198 male 
# ... with 77 more rows, and 6 more variables: gender <chr>, homeworld <chr>,
#   species <chr>, films <list>, vehicles <list>, starships <list>

同理,这两行代码的性质也是一样的

starwars %>% mutate_if(is.numeric, scale2, na.rm = TRUE)
starwars  %>% mutate(across(where(is.numeric), scale2, na.rm = TRUE))

使用where函数筛选出numeric的列,再使用across联合这些列,因此函数可以特定的穿过这些列,达到mutate_if的作用。

如果你想对数据框中的某列同时使用多个函数,使用list()。当同时使用多个function时,将会创建一个新的列,而不是像之前那样在原列上进行修饰。
eg:

 > head(iris)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
> iris %>% mutate_if(is.numeric, list(scale2, log)) %>% head()
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_fn1
1          5.1         3.5          1.4         0.2  setosa       -0.8976739
2          4.9         3.0          1.4         0.2  setosa       -1.1392005
3          4.7         3.2          1.3         0.2  setosa       -1.3807271
4          4.6         3.1          1.5         0.2  setosa       -1.5014904
5          5.0         3.6          1.4         0.2  setosa       -1.0184372
6          5.4         3.9          1.7         0.4  setosa       -0.5353840
  Sepal.Width_fn1 Petal.Length_fn1 Petal.Width_fn1 Sepal.Length_fn2
1      1.01560199        -1.335752       -1.311052         1.629241
2     -0.13153881        -1.335752       -1.311052         1.589235
3      0.32731751        -1.392399       -1.311052         1.547563
4      0.09788935        -1.279104       -1.311052         1.526056
5      1.24503015        -1.335752       -1.311052         1.609438
6      1.93331463        -1.165809       -1.048667         1.686399
  Sepal.Width_fn2 Petal.Length_fn2 Petal.Width_fn2
1        1.252763        0.3364722      -1.6094379
2        1.098612        0.3364722      -1.6094379
3        1.163151        0.2623643      -1.6094379
4        1.131402        0.4054651      -1.6094379
5        1.280934        0.3364722      -1.6094379
6        1.360977        0.5306283      -0.9162907

还可以进一步对function进行命名,注意下面的dataframe的列名与上面的不一样,冠以函数名。

> iris %>% mutate_if(is.numeric, list(scale = scale2, log = log)) %>% head()
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species Sepal.Length_scale
1          5.1         3.5          1.4         0.2  setosa         -0.8976739
2          4.9         3.0          1.4         0.2  setosa         -1.1392005
3          4.7         3.2          1.3         0.2  setosa         -1.3807271
4          4.6         3.1          1.5         0.2  setosa         -1.5014904
5          5.0         3.6          1.4         0.2  setosa         -1.0184372
6          5.4         3.9          1.7         0.4  setosa         -0.5353840
  Sepal.Width_scale Petal.Length_scale Petal.Width_scale Sepal.Length_log
1        1.01560199          -1.335752         -1.311052         1.629241
2       -0.13153881          -1.335752         -1.311052         1.589235
3        0.32731751          -1.392399         -1.311052         1.547563
4        0.09788935          -1.279104         -1.311052         1.526056
5        1.24503015          -1.335752         -1.311052         1.609438
6        1.93331463          -1.165809         -1.048667         1.686399
  Sepal.Width_log Petal.Length_log Petal.Width_log
1        1.252763        0.3364722      -1.6094379
2        1.098612        0.3364722      -1.6094379
3        1.163151        0.2623643      -1.6094379
4        1.131402        0.4054651      -1.6094379
5        1.280934        0.3364722      -1.6094379
6        1.360977        0.5306283      -0.9162907

mutate_all
mutate_all网页上没有过多的例子,但是根据其解释,应该是对所有的变量进行操作。

> a = matrix(rep(1:5,each =10),10) %>% as.data.frame()
> a
   V1 V2 V3 V4 V5
1   1  2  3  4  5
2   1  2  3  4  5
3   1  2  3  4  5
4   1  2  3  4  5
5   1  2  3  4  5
6   1  2  3  4  5
7   1  2  3  4  5
8   1  2  3  4  5
9   1  2  3  4  5
10  1  2  3  4  5
> mutate_all(a,funs(sum(.)))
   V1 V2 V3 V4 V5
1  10 20 30 40 50
2  10 20 30 40 50
3  10 20 30 40 50
4  10 20 30 40 50
5  10 20 30 40 50
6  10 20 30 40 50
7  10 20 30 40 50
8  10 20 30 40 50
9  10 20 30 40 50
10 10 20 30 40 50

补充一点:
调用funs时,可以按照例子那样自己写一个function,多个function使用list(),也可以使用~fun(.)调用。


image.png
starwars  %>%  mutate_at(c("height", "mass"), ~scale2(., na.rm =  TRUE))

总结
与mutate增加新变量不同,mutate的衍生函数主要是按列对数据赋予function,如果想增加按行,可以增加group_by以及rowwise函数。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容