如何正确使用R语言的函数——为什么有的模型结果不能使用summary函数查询?...

本篇来谈一个比较基础的问题:如何正确使用R语言的函数?

R的函数和数学上的函数类似——函数名后跟着圆括号,圆括号内是参数,参数可以赋值——因此用户能很容易理解。但也会有些读者对“数据结构”没有概念,对函数的使用也只是一知半解。

首先提出两个问题:

  • R环境中存在同名函数,R环境对此如何区分?

  • 同名函数意味着只是名称相同,实际不是一个函数,那判断同一函数和同名函数的依据是什么?反过来看,什么时候R环境会把同名函数误认为同一函数呢?

很多读者也会私信学堂君询问某些特定函数的用法,对此学堂君也一般建议读者去看函数的帮助文档。虽然看起来比较“敷衍”,但其实是一种正确学习R语言的方法。本篇就通过几个函数例子来证明这一点。

1 summary()函数

1.1 例1.1

summary()属于基础包中的函数,那究竟是哪个基础包呢?利用RStudio的自动联想功能,可以看出它来自base工具包。

c5e7373fa0d129e81d152d98bbcfd4e5.png

这其实有点违背直觉,因为使用summary()函数大多数情况是输出数学模型的结果,它理应在stats工具包里。

事实上,用来查看线性模型结果的summary()函数确实来自stats工具包。通过查看帮助文档可以验证这一点,如下图:

1aafa6be1297e7902222caa837e9d878.png

尽管现在还没有明确区分同一函数和同名函数的依据,但如果两个函数不在一个工具包里,那应该不会是同一个函数,而只能是同名函数。

其实,base工具包的summary()函数也十分常用。比如我们查看数据框变量的分布时会用到它:

summary(mtcars)

##       mpg             cyl             disp             hp       
##  Min.   :10.40   Min.   :4.000   Min.   : 71.1   Min.   : 52.0  
##  1st Qu.:15.43   1st Qu.:4.000   1st Qu.:120.8   1st Qu.: 96.5  
##  Median :19.20   Median :6.000   Median :196.3   Median :123.0  
##  Mean   :20.09   Mean   :6.188   Mean   :230.7   Mean   :146.7  
##  3rd Qu.:22.80   3rd Qu.:8.000   3rd Qu.:326.0   3rd Qu.:180.0  
##  Max.   :33.90   Max.   :8.000   Max.   :472.0   Max.   :335.0

可以不加区分地使用,也不需要加载工具包,读者会潜意识地认为上面这个summary()函数和下面这个是同一个函数:

model <- lm(mpg ~ qsec, data = mtcars)
summary(model)

## Call:
## lm(formula = mpg ~ qsec, data = mtcars)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -9.8760 -3.4539 -0.7203  2.2774 11.6491 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)  
## (Intercept)  -5.1140    10.0295  -0.510   0.6139  
## qsec          1.4121     0.5592   2.525   0.0171 *
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

1.2 例1.2

basestats都是R的基础包,都随R启动而自动加载,它们的函数也会始终处在R的环境中等待调用。从这个意义上说,上例中两个summary()函数和同在一个工具包也没什么区别。那真正意义上的同一工具包会存在同名但并不相同的函数吗?

base工具包为例,我们在帮助文档中找到summary()函数的语法结构:

722672b7f61e09fce5689e21e61cde91.png

通过第一个红框的内容可以看到,函数执行的功能取决于它第一个参数的“类型”,也就是“数据结构”。针对数据框、因子向量、矩阵等类型的对象,它执行的不是一个语法结构。

函数对应的英文是function,从这个意义说,这些summary()函数并不是同一个函数。不过考虑到可以在函数内部定义不同的功能,我们也可以将其看作是同一个函数,而它和定义一系列单一功能的summary()函数也没什么区别——因为R环境会根据第一个参数的数据结构加以区分。这也可以解释为什么basestats中的summary()函数在使用时不用区分了——因为它们针对的是不同类型的数据结构。

1.3 例1.3

我们再看stats包中的summary()函数。

之所以通过RStudio的自动联想功能查不到该包有summary()函数,是因为帮助文档中使用了后缀进行区分。

比如查看线性模型结果的是summary.lm()函数,查看广义线性模型的是summary.glm()函数,此外还有summary.aov()summary.nls()等函数。如下图所示:

494be9916c6f43fd446443f301319b75.png

尽管在使用时用的是同一个函数名,但帮助文档中对其进行区分,一定程度上也是有意将它们看作是不同的函数。原因在于,尽管都是“模型”,但是线性模型和广义线性模型所对应的对象并非是同一种数据结构,针对不同的模型要分别定义一个summary()函数。

回到推文标题,为什么有的模型结果不能使用summary()函数查询呢?是因为工具包的作者没有为这种类型的“模型”定义summary()函数。一个例子就是使用GWmodel工具包运行地理加权模型,通过summary()函数查询的结果如下所示(GWmodel | 地理加权模型(Ⅱ-1):地理加权主成分分析(GWPCA)):

library(GWmodel)
library(sf)
library(sp)
library(tidyverse)
data(Georgia)
data(GeorgiaCounties)
Gedu.df$AreaKey <- factor(Gedu.df$AreaKey)
dta <- Gedu.counties %>% st_as_sf() %>%
  left_join(Gedu.df, by = c("AREAKEY" = "AreaKey")) %>%
  as("Spatial")
formula <- PctPov ~ PctBlack + PctBach
bw.1 <- bw.gwr(formula, data = dta,
               approach = "aic",
               adaptive = T,
               kernel = "gaussian")
model.1 <- gwr.basic(formula, data = dta,
                     bw = bw.1,
                     adaptive = T,
                     kernel = "gaussian")
summary(model.1)
##               Length Class                    Mode
## GW.arguments   11    -none-                   list
## GW.diagnostic   8    -none-                   list
## lm             14    lm                       list
## SDF           159    SpatialPolygonsDataFrame S4  
## timings         5    -none-                   list
## this.call       6    -none-                   call
## Ftests          0    -none-                   list

很明显,这不是我们想象中模型结果该有的样子。通过查看GWmodel工具包的帮助文档也找不到summary()函数,而基础包stats不能运行地理加权模型,自然也不会为这种“模型”定义summary()函数。

那为什么在这里summary(model.1)语句还能输出结果呢(尽管不是所期望的结果)?因为这里执行的其实是base包中的summary()函数:

ls = list()
summary(ls)  
## Length  Class   Mode 
##      0   list   list

GWmodel的作者实际上是定义了一系列的print()函数来查询该模型的信息:

print(model.1)  
## 输出内容较长,有省略

##    ***********************************************************************
##    *          Results of Geographically Weighted Regression              *
##    ***********************************************************************
## 
##    *********************Model calibration information*********************
##    Kernel function: gaussian 
##    Adaptive bandwidth: 22 (number of nearest neighbours)
##    Regression points: the same locations as observations are used.
##    Distance metric: Euclidean distance metric is used.
## 
##    ****************Summary of GWR coefficient estimates:******************
##                  Min.  1st Qu.   Median  3rd Qu.    Max.
##    Intercept 10.38272 13.01826 14.76120 19.30086 20.6314
##    PctBlack   0.19714  0.23396  0.26714  0.29816  0.3677
##    PctBach   -0.65183 -0.55045 -0.37867 -0.28073 -0.1597
##    ************************Diagnostic information*************************
##    Number of data points: 159 
##    Effective number of parameters (2trace(S) - trace(S'S)): 14.82297 
##    Effective degrees of freedom (n-2trace(S) + trace(S'S)): 144.177 
##    AICc (GWR book, Fotheringham, et al. 2002, p. 61, eq 2.33): 867.0877 
##    AIC (GWR book, Fotheringham, et al. 2002,GWR p. 96, eq. 4.22): 852.3931 
##    BIC (GWR book, Fotheringham, et al. 2002,GWR p. 61, eq. 2.34): 736.8195 
##    Residual sum of squares: 1853.565 
##    R-square value:  0.7770154 
##    Adjusted R-square value:  0.75393

GWmodel工具包中的print()函数:

158a83ab3ab78e7934621226e75515a5.png

另外,我们知道base包中也有一个print()函数,但这里model.1的数据结构是gwrm类型,因此print(model)执行的是上图中print.gwrm()函数。

class(model.1)  
## [1] "gwrm"

当然,考虑到用户习惯,许多工具包会为它的模型定义一个summary()函数,比如运行生存模型的survival工具包,运行多层模型的lme4工具包等,但这也会给人一种基础包的summary()函数包打一切的错觉,碰到不按常规出牌的工具包可以会感到困惑。

2 filter()函数

现在知道,R环境能根据对象的数据结构区分同名函数。那如果函数名相同、对象数据结构也相同呢?

2.1 例2.1

dplyr工具包和基础包有一些同名的函数。当首次加载dplyr工具包时会出现如下提示:

library(dplyr)
## 载入程辑包:'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union

在加载dplyr后,R环境会将基础包的一些同名函数覆盖掉(或者说屏蔽),这样出现同名函数调用的就只能来自dplyr包。那为什么在上节的例子里,summary()print()等函数不会被覆盖呢?其实就是因为这里函数不仅同名,而且连对象数据结构也可以相同,R环境无法对其区分。

比如,来自dplyr包的filter()函数用于样本筛选,是一个很常用的函数,而stats包中也有这么一个函数,并且这两个函数的数据结构还有重叠。读者可以尝试在加载dplyr工具包前后分别运行下列代码:

x <- 1:100
filter(x, rep(1, 3))

加载前(重启R再运行):

x <- 1:100
filter(x, rep(1, 3))
## Time Series:
## Start = 1 
## End = 100 
## Frequency = 1 
##   [1]  NA   6   9  12  15  18  21  24  27  30  33  36  39  42  45  48  51  54
##  [19]  57  60  63  66  69  72  75  78  81  84  87  90  93  96  99 102 105 108
##  [37] 111 114 117 120 123 126 129 132 135 138 141 144 147 150 153 156 159 162
##  [55] 165 168 171 174 177 180 183 186 189 192 195 198 201 204 207 210 213 216
##  [73] 219 222 225 228 231 234 237 240 243 246 249 252 255 258 261 264 267 270
##  [91] 273 276 279 282 285 288 291 294 297  NA
  • 此时,R环境执行stats工具包中的函数,程序正常运行。

加载后:

library(dplyr)
x <- 1:100
filter(x, rep(1, 3))
# Error in UseMethod("filter") : 
#   no applicable method for 'filter' applied to an object of class "c('integer', 'numeric')"
  • 此时,R环境会认为该函数来自dplyr工具包,但由于后面的参数无法对应,程序运行出错。

解决办法是在函数名前加上工具包名两个冒号

x <- 1:100
stats::filter(x, rep(1, 3))
## Time Series:
## Start = 1 
## End = 100 
## Frequency = 1 
##   [1]  NA   6   9  12  15  18  21  24  27  30  33  36  39  42  45  48  51  54
##  [19]  57  60  63  66  69  72  75  78  81  84  87  90  93  96  99 102 105 108
##  [37] 111 114 117 120 123 126 129 132 135 138 141 144 147 150 153 156 159 162
##  [55] 165 168 171 174 177 180 183 186 189 192 195 198 201 204 207 210 213 216
##  [73] 219 222 225 228 231 234 237 240 243 246 249 252 255 258 261 264 267 270
##  [91] 273 276 279 282 285 288 291 294 297  NA

2.2 例2.2

上例中,程序运行出错会提示用户修改代码。但在一些情况下,程序能正常运行,但运行结果未必如预期。比如当运行语句lag(1:10, 2时,程序执行下面哪种情况取决于否加载了dplyr工具包:

stats::lag(1:10,2)
##  [1]  1  2  3  4  5  6  7  8  9 10
## attr(,"tsp")
## [1] -1  8  1

dplyr::lag(1:10, 2) 
##  [1] NA NA  1  2  3  4  5  6  7  8

3 总结

R环境能根据对象的数据结构区分同名函数;当数据结构相同时,R环境无法区分二者。

另外,学R,要多看帮助文档。


d20e0dcebec9c4bea22060034ca2b974.jpeg
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
R语言中的summary函数是一个非常常用的函数,它可以提供有关给定数据的统计摘要信息。根据引用中的说明,虽然在R环境中有多个summary函数,但它们针对的是不同类型的数据结构,因此可以将它们视为同一个函数。我们可以使用summary函数来获得数据的最小值、最大值、中位数、均值以及四分位数等统计信息。通过这些信息,我们可以更好地了解数据的分布和特征。 根据引用中的建议,对于特定函数的用法,我们可以查看函数的帮助文档。这是一种正确学习R语言的方法。对于summary函数,我们可以通过输入"?summary"来查看其帮助文档,并了解其各种参数和用法示例。 总结来说,R语言中的summary函数可以提供给定数据的统计摘要信息,帮助我们更好地理解数据的特征和分布。可以通过查看函数的帮助文档来了解更多关于summary函数的用法和参数。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [如何正确使用R语言函数——为什么有的模型结果不能使用summary函数查询?...](https://blog.csdn.net/weixin_54000907/article/details/126066802)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值