2 R语言函数
- Everything that exists is an object.
- Everything that happens is a function call.
本文摘抄于R Programming for Data Science
R 中的函数是“第一类对象”,这意味着可以像对待任何其他 R 对象一样对待它们。 重要的是,
- 函数可以作为参数传递给别的函数,对于各种的apply函数非常方便,比如
lapply()
和sapply()
,这一点会记录在向量化操作. - 函数可以嵌套,这样你就可以在另一个函数内部定义一个函数.
2.1 第一个函数
<- function() {
f # This is an empty function
}
# Functions have their own class
class(f)
## [1] "function"
# Execute this function
f()
## NULL
在函数内部调用其他函数, cat()
函数意思为 cut and pasted.类似于打印到输出台上。
<- function() {
f cat("Hello, world!\n")
}
f()
## Hello, world!
2.1.1 为什么用函数
In general, if you find yourself doing a lot of cutting and pasting, that’s usually a good sign that you might need to write a function.
函数主要的应用于,重复麻烦的任务中,如果我们要打印多行,一种方法是不断的重复输入相同的代码,这样做很笨拙。我们可以利用函数来完成这种任务。同时我们需要设定一个参数,比如这里的num
,我们调用函数的时候在“这个位置”上改成我们想要的量。
<- function(num) {
f for(i in seq_len(num)) {
cat("Hello, world!\n")
}
}
f(3)
## Hello, world!
## Hello, world!
## Hello, world!
2.1.2 函数的返回值
上面讨论的函数,它们并没有返回值(return),它们仅仅在控制台打印了”Hello, world!“,但是什么是返回值?如果我们定义了一个对象,例如一个向量,当我们输入这个向量的时候,会返回它的存储的量。这里解释的可能不大准确。
<- c(1:3)
v
# call v
v ## [1] 1 2 3
<- function(num) {
f <- "Hello, world!\n"
hello for(i in seq_len(num)) {
cat(hello)
}<- nchar(hello) * num
chars # 这里是返回值
chars
}
<- f(3)
meaningoflife ## Hello, world!
## Hello, world!
## Hello, world!
# 和上面调用向量有什么区别?
meaningoflife ## [1] 42
2.1.3 查询函数的文档
如果不知道函数的参数和使用方法,在Rstudio里,一般用?function
方式查询(注意没有括号),会显示在左边的Help中,当然也可以直接在Help的搜索框里查询.这里查到的是关于函数的非常全面的一个信息.
如果知识想看个大概的话,不加括号可以访问到函数的代码,可以“窥探”一下函数,这个只是查看,而没有说明怎么用.然后函数的参数可以用str()
(structure这个函数其他地方也有用)和args
(arguments参数)来查看,具体效果如下.
matrix## function (data = NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL)
## {
## if (is.object(data) || !is.atomic(data))
## data <- as.vector(data)
## .Internal(matrix(data, nrow, ncol, byrow, dimnames, missing(nrow),
## missing(ncol)))
## }
## <bytecode: 0x0000021a1cb0ff48>
## <environment: namespace:base>
str(matrix)
## function (data = NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL)
args(matrix)
## function (data = NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL)
## NULL
2.2 函数参数匹配
使用带参数的函数有多种方法。最好是按位置匹配参数
- 按照位置匹配参数
- 按照名字匹配参数
- 部分匹配
- 混用
传递的参数一定要和函数的参数匹配上,这个我是在Python学的时候深有体会,当时因为参数匹配错了,第二个参数的位置我放的第一个参数,导致程序出错,我还不知道咋回事.如果不想按位置放参数,就要参数的名字.
str(rnorm) # 查看函数的参数
## function (n, mean = 0, sd = 1)
<- rnorm(100, 2, 1) # 位置参数匹配
mydata
sd(mydata) # 函数第一个参数匹配,第二个参数默认
## [1] 1.101315
sd(x = mydata) # 声明参数名字匹配,第二个参数默认
## [1] 1.101315
sd(x = mydata, na.rm = FALSE)
## [1] 1.101315
sd(na.rm = FALSE, x = mydata)
## [1] 1.101315
# 这样做也可以,因为只有两个参数
sd(na.rm = FALSE, mydata)
## [1] 1.101315
最后一种,被称作部分匹配(partially matched),它会先把指明参数名称的匹配上,剩下没有指明名称的量会按照参数的位置进行匹配。
2.2.1 ...
参数
…参数是因为事先不知道要向函数传递多少个参数。比如像paste()
和cat()
这样的函数
args(paste)
## function (..., sep = " ", collapse = NULL, recycle0 = FALSE)
## NULL
args(cat)
## function (..., file = "", sep = " ", fill = FALSE, labels = NULL,
## append = FALSE)
## NULL
paste("A", "B")
## [1] "A B"
paste("A", "B", "hello")
## [1] "A B hello"
需要注意的是:...
的一个问题是,任何出现在参数列表中...
之后的参数都必须明确命名,不能部分匹配或位置匹配。
paste("a", "b", ":")
## [1] "a b :"
paste("a", "b", sep = ":")
## [1] "a:b"
paste("a", "b", se = ":") # 错误名称
## [1] "a b :"
2.4 一千以内的质数
ChatGPT生成
带有双重循环的代码:
# 生成 2 到 1000 的数字序列
<- 2:1000
numbers
# 创建一个空向量,用于存储质数
<- c()
primes
# 遍历每个数字,判断其是否为质数
for (num in numbers) {
# 定义一个变量,用于记录当前数字是否为质数
<- TRUE
is_prime
# 判断当前数字是否可以被比它小的数字整除
for (i in 2:(num - 1)) {
if (num %% i == 0) {
# 如果可以整除,则当前数字不是质数
<- FALSE
is_prime break
}
}
# 如果当前数字是质数,则将其添加到质数向量中
if (is_prime) {
<- c(primes, num)
primes
}
}
# 输出所有的质数
print(primes)
## [1] 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67
## [19] 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157
## [37] 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257
## [55] 263 269 271 277 281 283 293 307 311 313 317 331 337 347 349 353 359 367
## [73] 373 379 383 389 397 401 409 419 421 431 433 439 443 449 457 461 463 467
## [91] 479 487 491 499 503 509 521 523 541 547 557 563 569 571 577 587 593 599
## [109] 601 607 613 617 619 631 641 643 647 653 659 661 673 677 683 691 701 709
## [127] 719 727 733 739 743 751 757 761 769 773 787 797 809 811 821 823 827 829
## [145] 839 853 857 859 863 877 881 883 887 907 911 919 929 937 941 947 953 967
## [163] 971 977 983 991 997
这段代码使用了一种名为埃拉托斯特尼筛法的方法,可以非常高效地筛选出一定范围内的所有质数,而且没有循环。
首先,定义了一个名为 is_prime 的向量,用于标记每个数字是否为质数。将 0 和 1 标记为非质数。然后,从 2 开始遍历每个数字,如果当前数字是质数,则将其倍数(除了它本身)标记为非质数。这个过程会一直进行到数字的平方大于 1000 为止。
最后,输出所有被标记为质数的数字。这个方法虽然没有循环,但是它的效率非常高,可以在极短的时间内输出 1000 以内所有的质数。
# 生成 2 到 1000 的数字序列
<- 2:1000
numbers
# 定义一个向量,用于判断每个数字是否为质数
<- rep(TRUE, length(numbers))
is_prime
# 将 0 和 1 标记为非质数
1:2] <- FALSE
is_prime[
# 判断每个数字是否为质数
for (i in 2:sqrt(length(numbers))) {
if (is_prime[i]) {
# 将当前数字的倍数标记为非质数
^2:length(numbers):i] <- FALSE
is_prime[i
}
}## Warning in i^2:length(numbers):i: numerical expression has 991 elements: only
## the first used
## Warning in i^2:length(numbers):i: numerical expression has 900 elements: only
## the first used
# 输出所有的质数
print(numbers[is_prime])
## [1] 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
## [16] 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
## [31] 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
## [46] 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
## [61] 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
## [76] 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
## [91] 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
## [106] 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
## [121] 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
## [136] 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
## [151] 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
## [166] 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
## [181] 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
## [196] 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
## [211] 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
## [226] 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
## [241] 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
## [256] 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
## [271] 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
## [286] 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
## [301] 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
## [316] 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
## [331] 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
## [346] 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
## [361] 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
## [376] 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
## [391] 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
## [406] 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
## [421] 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
## [436] 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
## [451] 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
## [466] 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581
## [481] 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
## [496] 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
## [511] 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626
## [526] 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
## [541] 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
## [556] 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
## [571] 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
## [586] 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701
## [601] 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
## [616] 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
## [631] 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
## [646] 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761
## [661] 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
## [676] 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
## [691] 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
## [706] 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
## [721] 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836
## [736] 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851
## [751] 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866
## [766] 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881
## [781] 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
## [796] 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
## [811] 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
## [826] 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941
## [841] 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956
## [856] 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971
## [871] 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
## [886] 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
R语言提供了很多用于质数计算的包。其中,最常用的是 primes 包,该包提供了多种方法来计算质数,包括试除法、线性筛法、分段线性筛法、米勒-拉宾素测试等。