2019-09-30自建函数用于数据分析

2019-09-30  本文已影响0人  iColors

原文https://www.njtierney.com/post/2019/09/29/unexpected-function/

1.R语言允许使用函数作为参数。
2.在一个函数内部的函数可以自行修改。

啥意思呢?先创建一个自己的函数:

my_fun <- function(x, fun){
  fun(x)
}

现在可以输入任何函数作为这个函数的参数。
以'dplyr'包的stroms数据为例。

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
storms
## # A tibble: 10,010 x 13
##    name   year month   day  hour   lat  long status category  wind pressure
##    <chr> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <chr>  <ord>    <int>    <int>
##  1 Amy    1975     6    27     0  27.5 -79   tropi… -1          25     1013
##  2 Amy    1975     6    27     6  28.5 -79   tropi… -1          25     1013
##  3 Amy    1975     6    27    12  29.5 -79   tropi… -1          25     1013
##  4 Amy    1975     6    27    18  30.5 -79   tropi… -1          25     1013
##  5 Amy    1975     6    28     0  31.5 -78.8 tropi… -1          25     1012
##  6 Amy    1975     6    28     6  32.4 -78.7 tropi… -1          25     1012
##  7 Amy    1975     6    28    12  33.3 -78   tropi… -1          25     1011
##  8 Amy    1975     6    28    18  34   -77   tropi… -1          30     1006
##  9 Amy    1975     6    29     0  34.4 -75.8 tropi… 0           35     1004
## 10 Amy    1975     6    29     6  34   -74.8 tropi… 0           40     1002
## # … with 10,000 more rows, and 2 more variables: ts_diameter <dbl>,
## #   hu_diameter <dbl>

计算wind的均值:

my_fun(storms$wind, mean)
## [1] 53.495

也可以计算标准差、变异系数、中位数

my_fun(storms$wind, sd)
## [1] 26.21387
my_fun(storms$wind, var)
## [1] 687.1668
my_fun(storms$wind, median)
## [1] 45

更进一步,如果你想为按月汇总storms的数据,怎么办?

storms %>% 
  group_by(month) %>%
  summarise(wind_summary = mean(wind))
## # A tibble: 10 x 2
##    month wind_summary
##    <dbl>        <dbl>
##  1     1         45.7
##  2     4         44.6
##  3     5         36.3
##  4     6         37.8
##  5     7         41.2
##  6     8         52.1
##  7     9         58.0
##  8    10         54.6
##  9    11         52.5
## 10    12         47.9

可以重复代码,把平均值函数改成其他函数就可以了,比如sd值。

storms %>% 
  group_by(month) %>%
  summarise(wind_summary = sd(wind))
## # A tibble: 10 x 2
##    month wind_summary
##    <dbl>        <dbl>
##  1     1         9.08
##  2     4         5.94
##  3     5         9.57
##  4     6        13.4 
##  5     7        19.1 
##  6     8        26.0 
##  7     9        28.2 
##  8    10        25.3 
##  9    11        22.0 
## 10    12        14.6

如此反复,周而复始,大脑感到很是乏累,有一个声音在脑海中响起:“别像猪一样”。
为了避免反复带来的麻烦,自己创建一个计算平均值的函数:

storms_wind_summary <- function(fun){
  storms %>%
    group_by(month) %>%
    summarise(wind_summary = fun(wind))
}

现在就可以轻松传递函数名字给我们自己建立的函数了,比如mean:

storms_wind_summary(mean)
## # A tibble: 10 x 2
##    month wind_summary
##    <dbl>        <dbl>
##  1     1         45.7
##  2     4         44.6
##  3     5         36.3
##  4     6         37.8
##  5     7         41.2
##  6     8         52.1
##  7     9         58.0
##  8    10         54.6
##  9    11         52.5
## 10    12         47.9

或者其他任何函数:

storms_wind_summary(sd)
## # A tibble: 10 x 2
##    month wind_summary
##    <dbl>        <dbl>
##  1     1         9.08
##  2     4         5.94
##  3     5         9.57
##  4     6        13.4 
##  5     7        19.1 
##  6     8        26.0 
##  7     9        28.2 
##  8    10        25.3 
##  9    11        22.0 
## 10    12        14.6
storms_wind_summary(var)
## # A tibble: 10 x 2
##    month wind_summary
##    <dbl>        <dbl>
##  1     1         82.5
##  2     4         35.3
##  3     5         91.5
##  4     6        180. 
##  5     7        365. 
##  6     8        678. 
##  7     9        793. 
##  8    10        638. 
##  9    11        482. 
## 10    12        213.
storms_wind_summary(median)
## # A tibble: 10 x 2
##    month wind_summary
##    <dbl>        <dbl>
##  1     1         50  
##  2     4         45  
##  3     5         35  
##  4     6         35  
##  5     7         37.5
##  6     8         45  
##  7     9         50  
##  8    10         50  
##  9    11         50  
## 10    12         45

甚至传递自己建立的函数为参数:

range_diff <- function(x){
  diff(range(x))
}
  
storms_wind_summary(range_diff)
## # A tibble: 10 x 2
##    month wind_summary
##    <dbl>        <int>
##  1     1           25
##  2     4           15
##  3     5           35
##  4     6           70
##  5     7          130
##  6     8          140
##  7     9          145
##  8    10          145
##  9    11          120
## 10    12           50

怎么样,看起来不错吧。自己就可以操纵函数。

更上一层楼

可以用summarise_at实现相同的目的:

storms_wind_summary <- function(fun){
  storms %>%
    group_by(month) %>%
    summarise_at(.vars = vars(wind),
                 .funs = list(fun))
}

storms_wind_summary(mean)
## # A tibble: 10 x 2
##    month  wind
##    <dbl> <dbl>
##  1     1  45.7
##  2     4  44.6
##  3     5  36.3
##  4     6  37.8
##  5     7  41.2
##  6     8  52.1
##  7     9  58.0
##  8    10  54.6
##  9    11  52.5
## 10    12  47.9
storms_wind_summary(median)
## # A tibble: 10 x 2
##    month  wind
##    <dbl> <dbl>
##  1     1  50  
##  2     4  45  
##  3     5  35  
##  4     6  35  
##  5     7  37.5
##  6     8  45  
##  7     9  50  
##  8    10  50  
##  9    11  50  
## 10    12  45

如果想传递许多函数,比如同时计算mean、median、sd、variance,怎么办?
可以用...来传递给函数,允许输入任何数目的函数为参数:

storms_wind_summary <- function(...){
  storms %>%
    group_by(month) %>%
    summarise_at(.vars = vars(wind),
                 .funs = list(...))
}


storms_wind_summary(median, mean, max)
## # A tibble: 10 x 4
##    month   fn1   fn2   fn3
##    <dbl> <dbl> <dbl> <int>
##  1     1  50    45.7    55
##  2     4  45    44.6    50
##  3     5  35    36.3    60
##  4     6  35    37.8    80
##  5     7  37.5  41.2   140
##  6     8  45    52.1   150
##  7     9  50    58.0   160
##  8    10  50    54.6   160
##  9    11  50    52.5   135
## 10    12  45    47.9    75
这些技巧虽然简单,在数据分析中经常会用到,灵活掌握就能提高工作效率,减少不必要的重复劳动!!!
上一篇下一篇

猜你喜欢

热点阅读