Learn R 笔记(PART1)

作者: Angeladaddy | 来源:发表于2019-06-15 23:12 被阅读0次

    chp01_简介

    mean(1:5)
    ?mean
    ?"+"
    # 搜索所有包含 "plotting" 的主题
    ??plotting
    help.search("plotting")
    # 搜索所有与 regression model 相关的主题
    ??"regression model" 
    help.search("regression model")
    # apropos 函数能找到匹配其输入的变量(以及函数)
    a_vector <- c(1:10)
    apropos("vector")
    apropos("z$")
    
    # example函数查看它们。也有一些较长的概念演示,你可以通过 demo 函数查看
    example(plot)
    demo(plotmath) 
    
    
    # 使用 browseVignettes 来浏览所有在你机器上的片段
    browseVignettes()
    # 可以使用 vignette 函数访问一个特定的片断
    vignette("Sweave", package = "utils")
    #  RSiteSearch ,它会查询整个 http://search.r-project.org 网站的包
    RSiteSearch("{Bayesian regression}")
    
    

    chp02_科学计算

    rm(list = ls())
    
    # 在 R 中,向量化有几种含义,其中最常见的含义是:运算符或函数能作用于向量中的每个元
    # 素,而无需显式地编写循环语句(这种内置的基于元素的隐式循环也远远快于显式地写循环
    # 语句)。向量化的第二个含义是:当一个函数把一个向量作为输入时,能计算汇总统计
    
    # 运算符号用在向量上,将对每一项进行运算
    a <- 1:5+6:10 # 7  9 11 13 15
    b <- -2:2 * -2:2 # 4 1 0 1 4
    c <- 1:3 / 3 # 0.3333333 0.6666667 1.0000000
    
    # R 还包含了多种数学函数。有三角函数( sin 、 cos 、 tan ,以及相反的 asin 、 acos 和
    # atan )、对数和指数( log 和 exp ,以及它们的变种 log1p 和 expm1 ,这两个函数对那些非常
    # 小的 x 值能更加精确地计算 log(1 + x) 和 exp(x - 1) 的值),以及几乎所有其他你能想到
    # 的数学函数。
    
    # 比较
    c(3, 4 - 1, 1 + 1 + 1) == 3 #  TRUE TRUE TRUE
    
    # R 还提供了 all.equal 函数用于检查数字是否相等。它提供了一个容忍度(tolerance level,
    # 默认情况下为 1.5e-8 ),因而那些小于此容忍度的舍入误差将被忽略:
    # 比较值一样时返回TRUE
    sqrt(2)^2==2 #FALSE
    all.equal(sqrt(2) ^ 2, 2) #TRUE
    # 比较值不一样时返回差值, 如果你需要它们在比较后返回
    # 的是一个 TRUE 或 FALSE 值,则应把 all.equal 函数嵌入 isTRUE 函数中调用
    isTRUE(all.equal(sqrt(2) ^ 2, 3))
    
    # 我们可以使用 <- 或 = 给(本地)变
    # 量赋值,虽然由于历史原因, <- 是首选。
    # 还可使用 <<- 来对全局变量赋值
    x <<- exp(exp(1))
    
    
    # R 支持四种特殊值: Inf 、 -Inf 、 NaN 和 NA 。显然,前两个分别是正负
    # 无穷,而后两个则需做些解释。 NaN 为“不是一个数”(not-a-number)的缩写,它意味着
    # 我们的计算或没有数学意义,或无法正确执行。 NA 是“不可用”(not available)的缩写,
    # 并代表缺失值
    
    # TRUE 和 FALSE 是 R 中的保留字:你不能创建以它们命名的变量(但可使用它们的小写或大
    # 小写混合,如 True )。当你启动 R 时,变量 T 和 F 已被系统默认定义为 TRUE 和 FALSE 。虽
    # 然这能让你少打点字,但也会造成很大的问题。 T 和 F 不是保留字,因此用户可以重新定
    # 义它们。这意味着你可以在命令行中使用它们的缩写名称,但如果你的代码需要与他人的
    # 代码交互(特别是当他们的代码涉及时间、温度或数学函数时),请避免使用这两个缩写。
    
    
    # 在 R 中有三个向量化逻辑运算符:
    # ! • 代表非操作
    # & • 代表与操作
    # | • 代表或操作
    
    x <- 1:10 >=5 #  FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRU
    !x #  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE
    y <- 1:10 %% 2 == 0
    x&y # FALSE FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE  TRUE
    
    
    # 其他两个比较有用的处理逻辑向量的函数是 any 和 all
    any(c(FALSE, FALSE, FALSE))
    all(c(FALSE, TRUE, FALSE))
    
    

    chp03_检查变量和工作区

    # R 没有标量类型(scalar type)在 R 中“最小的”数据类型是向量。
    #使用class,typeof,mode,storage.mode
    a = c(1:10)
    class(a) #"integer"
    typeof(a)#"integer"
    mode(a) # "numeric"
    storage.mode(a) # "integer"
    #  R 包含三种不同类别的数值变量:浮点值 numeric 、整数 integer 和复数 complex
    class(1) # "numeric"
    class(1L) # "integer", 整形必须加L
    class(3+1i) # complex
    
    # R 不区分整个字符串和单个字符——只包含一个字符的字符串与其他字符串的处理相同
    class("1") # "character"
    
    # 因子与其他语言中的枚举类似
    gender <- factor(c("male", "female", "female", "male", "female"))
    levels(gender) # "female" "male"   默认情况下因子水平按字母顺序分配。
    # 在底层,因子的值被存储为整数而非字符
    as.integer(gender) # 2 1 1 2 1
    as.character(gender) # "male"   "female" "female" "male"   "female"
    
    
    # 类型检查和转换
    # 查看在 base 包中所有的 is 函数
    ls(pattern = "^is",baseenv())
    # 大部分的 is* 函数都有与之对应的 as* 函数
    x <- "123.456"
    as(x, "numeric") # 尽量不要用这种写法
    as.numeric(x)# 应该使用这种写法
    class(x) <- "numeric" # 这种写法也不推荐
    
    # 查看对象信息的方法
    # summary,head,str
    
    # unclass函数显示底层信息
    info = unclass(gender)
    # attributes 函数能显示当前对像的所有属性列表
    attributes(gender)
    # 一个好方法是结合 View 和 head 函数来查看数据框的前几行
    View(head(mtcars, 50)) # 查看前 50 行
    
    

    chp04_向量、矩阵和数组

    rm(list = ls())
    # 冒号运算符 : 来创建从某个数到另一个数的数字序列,以及用 c 函数来拼接数值和向量,以创建更长的向量
    a = 8.5:4.2 # 8.5 7.5 6.5 5.5 4.5
    b = c(1:3,4,5:10) # c函数用来拼接处更长向量
    # vector 函数能创建一个指定类型和长度的矢量。其结果中的值可为零、 FALSE 、空字符串,或任何相当于“什么都没有”(nothing)的类型:
    c = vector("numeric",5) # 等同于 numeric(5) 
    c = vector("complex",5) # 等同于 complex(5)
    c = vector("logical",5) # 等同于 logical(5)
    c = vector("character",5) # 等同于 character(5)
    c = vector("list",5) # 等同于 list(5)
    
    
    # 生成序列
    d = seq.int(3,15,3) # 等同于 3:15,但可以指定步长
    #  seq_len 函数将创建一个从 1 到它的输入值的序列
    e = seq.int(0)
    # seq_along 创建一个从 1 开始、长度为其输入值的序列:
    f <- c("Peter", "Piper", "picked", "a", "peck", "of", "pickled", "peppers")
    for(i in seq_along(f)) print(f[i])
    
    # 长度
    length(1:5)
    sn <- c("Sheena", "leads", "Sheila", "needs")
    length(sn) # 4
    #nchar 计算每个字符串中字符数的长度
    nchar(sn)
    
    # 命名
    # 创建时命名
    g = c(apple = 1, banana = 2, "kiwi fruit" = 3, 4)
    # 也可以在向量创建后用 names 函数为元素添加名字:
    h = 1:4
    names(h) = c("apple", "bananas", "kiwi fruit", "")
    
    
    # 索引向量(重要)
    # 给向量传入正数,它会返回此位置上的向量元素切片。它的第一个位置是 1 (而不像其他某些语言一样是 0) 。
    # 给向量传入负数,它会返回一个向量切片,它将包含除了这些位置以外的所有元素。
    # 给向量传入一个逻辑向量,它会返回一个向量切片,里面只包含索引为 TRUE 的元素。
    # 对于已命名的向量,给向量传入命名的字符向量,将会返回向量中包含这些名字的元素切片。
    
    x = (1:5) ^2
    names(x) = c("one","two","three","four","five")
    # 以下4种 方式都返回相同值
    x[c(1,3,5)]
    x[c(-2,-4)]
    x[c(TRUE,FALSE,TRUE,FALSE,TRUE)]
    x[c("one","three","five")]
    x[c(TRUE,FALSE)] # 选取下标单数(true,false循环作用于向量每一项)
    # which函数将返回逻辑向量中为TRUE的位置
    which(x>5) #   3     4     5, 注意返回的是下标
    x[which(x>5)] # 这样才能返回值
    # which.min 和 which.max 分别是 which(min(x)) 和 which(max(x)) 的简写:
    which.min(x)
    which.max(x)
    
    
    # 向量循环和重复
    # 如果我们把一个单独的数字与向量相加,则向量的每个元素都会与该数字相加:
    # 将两个向量相加时,R 将会循环较短向量中的元素以配合较长的那个,如果长向量的长度不是短向量长度的倍数,将出现一个警告:
    # rep 函数允许我们重复使用元素来创建矢量:
    
    rep(1:5, 3)
    ## [1] 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
    rep(1:5, each = 3)
    ## [1] 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5
    rep(1:5, times = 1:5)
    ## [1] 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5
    rep(1:5, length.out = 7)
    ## [1] 1 2 3 4 5 1 2
    
    
    # 矩阵和数组
    # 数组能存放多维矩形数据。“矩形”是指每行的长度都相等,且每列和其他长度也是如此。
    # 矩阵是二维数组的特例。
    
    # 可以使用 array 函数创建一个数组,为它们传入两个向量(值和维度)作为参数。另外,
    # 你也可以为每个维度命名:
    # 一个3维数组实例
    arr = array(1:24,dim = c(4,3,2),dimnames = list(
      c("one", "two", "three", "four"),
      c("ein", "zwei", "drei"),
      c("un", "deux")
    ))
    
    # 创建矩阵的语法非常类似,但无需传递维度 dim 参数,只要指定行数或列数即可:
    m = matrix(1:12,nrow = 4,dimnames = list(
      c("one", "two", "three", "four"),
      c("ein", "zwei", "drei")
    ))
    # 该矩阵也可以用 array 函数来创建
    m = array(1:12,dim = c(4,3),dimnames = list(
      c("one", "two", "three", "four"),
      c("ein", "zwei", "drei") 
    ))
    # 创建矩阵时,传入的值会按列填充矩阵。也可指定参数 byrow = TRUE 来按行填充矩阵:
    m = matrix(1:12,nrow = 4,dimnames = list(
      c("one", "two", "three", "four"),
      c("ein", "zwei", "drei")
    ),byrow = TRUE)
    
    
    # 行、列和维度
    dim(arr) # 4 3 2
    nrow(m)
    ncol(m)
    # length 用于矩阵和数组将返回所有维度的乘积
    length(arr) # 4*3*2 = 24
    # 把 nrow 、 ncol 和 dim 用于向量时将返回 NULL 值。
    # 向量中与 nrow 和 ncol 相对的函数是 NROW 和NCOL 
    recaman <- c(0, 1, 3, 6, 2, 7, 13, 20)
    nrow(recaman)
    ## NULL
    NROW(recaman)
    ## [1] 8
    ncol(recaman)
    ## NULL
    NCOL(recaman)
    ## [1] 1
    dim(recaman)
    
    # 行名、列名和维度名
    rownames(arr)
    ## [1] "one" "two" "three" "four"
    colnames(arr)
    ## [1] "ein" "zwei" "drei"
    dimnames(arr)
    
    # 索引数组
    arr[1, c("one", "drei")] # 在第一行、第二列和第三列的两个元素
    # 要包括所有维度,则只需置空相应的下标:
    a = m[1,]
    
    #合并矩阵
    # 通过使用 cbind 和 rbind 函数按行和列来绑定两个矩阵,能更自然地合并它们:
    another_matrix <- matrix(
      seq.int(2, 24, 2),
      nrow = 4, 
      dimnames = list(
        c("five", "six", "seven", "eight"),
        c("vier", "funf", "sechs")
      )
    )
    
    merge1 = cbind(m,another_matrix)
    merge2 = rbind(m,another_matrix)
    
    
    ## 数组、矩阵可以进行运算
    
    ## t 函数用于转置矩阵(但不能转置更高维的数组,其中的概念没有被明确定义):
    turnedM= t(m)
    
    

    05. 列表和数据框

    rm(list=ls())
    # 向量、矩阵和数组所包含的元素的类型都是相同的。列表和数据框是两种特
    # 殊的类型,允许我们把不同类型的数据合并到单一变量中。
    
    # 列表其实是一个向量,但其中的每个元素类型可以不同
    
    a_list = list(c(1:10),month.abb,matrix(1:4,nrow = 2),asin)
    # [[1]]
    # [1]  1  2  3  4  5  6  7  8  9 10
    # 
    # [[2]]
    # [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"
    # 
    # [[3]]
    # [,1] [,2]
    # [1,]    1    3
    # [2,]    2    4
    # 
    # [[4]]
    # function (x)  .Primitive("asin")
    
    # 与向量的命名类似,你可以在构造列表时就给元素命名,或在构造之后使用 names 函数命名
    names(a_list) <- c("catalan", "months", "involutary", "arcsin")
    
    the_same_list <- list(
      catalan = c(1, 1, 2, 5, 14, 42),
      months = month.abb,
      involutary = matrix(c(3, -8, 1, -3), nrow = 2),
      arcsin = asin
    )
    
    
    # 原子变量和递归变量
    # 由于列表具有这种把其他列表包含在内的能力,它被认为是递归变量。
    # 与之相对,向量、矩阵和数组则是原子变量
    # 函数 is.recursive 和 is.atomic 可测试它们的类型
    
    is.recursive(list())
    is.atomic(list())
    
    # 只能使用NROW和NCOL作用在列表上(与矢量相同)
    NROW(a_list) # 4
    NCOL(a_list) # 1
    
    # 索引列表
    l <- list(
      first = 1,
      second = 2,
      third = list(
        alpha = 3.1,
        beta = 3.2
      )
    )
    # 以下索引操作[]都将返回另一个列表
    l[1]
    l[1:2]
    l[-3]
    l[c("first","second")]
    l[c(TRUE,FALSE,TRUE)]
    is.list(l[1]) # TRUE
    # 我们要访问的是列表元素中的内容,使用[[]]返回索引下标
    # [[number]]
    # [["colname"]]
    
    l[[1]] 
    l[[3]]
    l[["first"]]
    is.list(l[[1]]) # FALSE
    
    # 使用$ 访问列表元素
    l$first
    l$third$alpha
    
    # 向量和列表之间的转换
    # 向量可使用函数 as.list 函数来转换成列表
    v1 <- c(1:10)
    l1 <- as.list(v1)
    
    # 如果一个列表各个元素都是标量,可以通过as函数转换为向量
    list2 = list(1,3,5,7)
    as.numeric(list2)
    
    # 但如果列表中含有非标量元素,要使用unlist函数
    list3 = list(a=c(1:10),b=c("aa","bb","bb"),c = rep("x",10))
    target = unlist(list3)
    # 可以看到列表被“拍平”了
    # a1   a2   a3   a4   a5   a6   a7   a8   a9  a10   b1   b2   b3   c1   c2   c3   c4   c5   c6   c7   c8   c9  c10 
    # "1"  "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9" "10" "aa" "bb" "bb"  "x"  "x"  "x"  "x"  "x"  "x"  "x"  "x"  "x"  "x"
    class(target) # [1] "character"
    
    
    # 列表合并
    # 提示:cbind和rbind可以用于合并列表,但最好不要用
    # 使用c来拼合列表
    c(list(a = 1, b = 2), list(3))
    
    
    # NULL
    # NULL最常被用在列表中
    uk_bank_holidays_2013 <- list(
      Jan = "New Year's Day",
      Feb = NULL,
      Mar = "Good Friday",
      Apr = "Easter Monday",
      May = c("Early May Bank Holiday", "Spring Bank Holiday"),
      Jun = NULL,
      Jul = NULL,
      Aug = "Summer Bank Holiday",
      Sep = NULL,
      Oct = NULL,
      Nov = NULL,
      Dec = c("Christmas Day", "Boxing Day")
    )
    
    # NULL是空,NA是缺失值
    # NULL不占空间,NA占空间
    length(NULL) #0
    length(NA) #1
    
    is.null(NULL) #TRUE
    is.null(NA) # FALSE
    
    
    # 将NULL赋值给列表中的元素可以删除元素
    uk_bank_holidays_2013$Jan=NULL #Jan元素被删除
    # 如果想将NULL值赋给列表元素,需要使用list(NULL)
    uk_bank_holidays_2013$Mar=list(NULL)
    
    
    
    
    
    # 数据框
    # 1.每个元素具有相同的长度
    # 2.可被看作是每列可存储不同数据类型的矩阵,几乎所有用于矩阵的函数亦可用在数据框上。
    # 3.或是非嵌套的列表
    # 4.每列的类型可与其他列不同,但在同一列中的元素类型必须相同
    
    # 创建数据框,注意,每行的元素长度必须相等
    # 如果把letters[1:5]改为[1:6]将会报错
    a_data_frame <- data.frame(
      x = letters[1:5],
      y = rnorm(5),
      z = runif(5) > 0.5
    )
    
    
    
    # 如果输入的任何向量有名称,那么行名称就取自第一个向量名称。
    y <- rnorm(5)
    names(y) <- month.name[1:5]
    data.frame(
      x = letters[1:5],
      y = y,
      z = runif(5) > 0.5
    )
    ## x y z
    ## January a -0.9373 FALSE
    ## February b 0.7314 TRUE
    ## March c -0.3030 TRUE
    ## April d -1.3307 FALSE
    ## May e -0.6857 FALSE
    
    # 这种命名规则可通过给 data.frame 函数传入参数 row.names = NULL 覆盖掉:
    data.frame(
      x = letters[1:5],
      y = y,
      z = runif(5) > 0.5,
      row.names = NULL
    )
    
    # 另外,还可以通过给 row.names 传入一个向量来为每行命名
    data.frame(
      x = letters[1:5],
      y = y,
      z = runif(5) > 0.5,
      row.names = c("Jackie", "Tito", "Jermaine", "Marlon", "Michael")
    )
    
    
    # 注意,length用于数据框将返回ncol,names将返回colnames
    # 建议你避开这两个函数,而使用 ncol 和 colnames
    length(a_data_frame)
    #可以使用不同长度的向量来创建数据框,只要长度较短的向量能刚好循环至总长度。从技
    # 术上讲,所有向量长度的最小公倍数必须与最长向量的长度相等:
    data.frame( # 长度 1、2 和 4 是 OK 的
      x = 1, # 循环 4 次
      y = 2:3, # 循环 2 次
      z = 4:7 # 最长的输入,不需要循环
    )
    ##  x y z
    ## 1 1 2 4
    ## 2 1 3 5
    ## 3 1 2 6
    ## 4 1 3 7
    
    
    # 创建数据框时的另一个要点为:在默认情况下,列名必须是唯一且有效的变量名称。此功
    # 能可通过给 data.frame 传入 check.names = FALSE 来关闭:
    data.frame(
      "A column" = letters[1:5],
      "!@#$%^&*()" = rnorm(5),
      "..." = runif(5) > 0.5,
      check.names = FALSE
    )
    ## A column !@#$%^&*() ...
    ## 1 a 0.32940 TRUE
    ## 2 b -1.81969 TRUE
    ## 3 c 0.22951 FALSE
    ## 4 d -0.06705 TRUE
    ## 5 e -1.58005 TRUE
    
    
    # 索引数据框
    # 比如:a_data_frame是一个3行5列的数据框
    a_data_frame[1:2,2:3]
    # y     z
    # 1 -1.04397313 FALSE
    # 2  0.01893394 FALSE
    a_data_frame[c(FALSE, TRUE, TRUE, FALSE, FALSE), c("x", "y")]
    #    如果只选择一个列,其结果将被简化为一个向量 
    class(a_data_frame[2:3,3]) # logical
    
    # 选择数据框中的某个子集
    # 选择y列>0或者z列为TRUE的行的x列
    a_data_frame[a_data_frame$y > 0 | a_data_frame$z, "x"]
    # subset函数可以干的更漂亮
    # subset(x, subset, select, drop = FALSE, ...)
    subset(a_data_frame, y > 0 | z, x)
    
    # t转置
    # 数据框可使用 t 函数进行转置。但在此过程中,所有的列(它们即将变成行) 
    # 将被转换为相同的类型,然后将变成一个矩阵:
    b = t(a_data_frame)
    ## [,1] [,2] [,3] [,4] [,5]
    ## x "a" "b" "c" "d" "e"
    ## y " 0.17581" " 0.06894" " 0.74217" " 0.72816" "-0.28940"
    ## z "TRUE" "TRUE" "TRUE" "TRUE" "TRUE"
    class(b) # matrix
    
    # rbind,cbind,merge
    # 数据框使用rbind没有任何问题
    # 使用cbind要注意,其不会对列名做重复检查
    another_data_frame <- data.frame( # 与 a_data_frame 有相同的 cols ,不过次序不同
      z = rlnorm(5), # 对数分布的数
      y = sample(5), # 1 到 5 随机排列的数
      x = letters[3:7]
    )
    cbind(a_data_frame, another_data_frame)
    ## x y z z y x
    ## 1 a 0.17581 TRUE 0.8714 1 c
    ## 2 b 0.06894 TRUE 0.2432 3 d
    ## 3 c 0.74217 TRUE 2.3498 4 e
    ## 4 d 0.72816 TRUE 2.0263 5 f
    ## 5 e -0.28940 TRUE 1.7145 2 g
    
    # 当两个数据框有相同的列时,可使用 merge 函数合并
    merge(a_data_frame, another_data_frame, by = "x")
    ## x y.x z.x z.y y.y
    ## 1 c 0.7422 TRUE 0.8714 1
    ## 2 d 0.7282 TRUE 0.2432 3
    ## 3 e -0.2894 TRUE 2.3498 5
    
    # 如果数据框中只包含数值,那么 colSums 和 colMeans 函数可分别用于计算每列的总和和平
    # 均值。同样地, rowSums 和 rowMeans 将计算每一行的总和及平均值:
    

    chp6_环境和函数

    rm(list = ls())
    # 使用 new.env 函数创建环境
    my_env = new.env()
    # 向环境中指定变量
    my_env$aaa = c(1:10)
    my_env[["bbb"]] = c(1:10)
    # assign函数等价
    assign("ccc",c(1:10),my_env)
    # assign 的对应函数是 get
    get("ccc",my_env)
    #ls/ls.str显示环境所有内容
    ls(envir = my_env)
    ls.str(envir = my_env)
    # exists判断变量是否在环境中
    exists("f",my_env)
    # 使用as.list从环境转为列表
    env_list = as.list(my_env)
    # 还可以使用list2env转换为环境
    env1 = list2env(env_list)
    # 使用as.environment从列表转为环境
    env2 = as.environment(env_list)
    # globalenv获取全局变量
    globalv <<- c(3:10)
    get("globalv",envir = globalenv())
    
    
    
    # 函数
    rt(1000,40,40)
    # R 的函数不需要return
    traingle <- function(x,y){
      sqrt(x^2+y^2)
    }
    # formals和args函数返回函数参数列表
    formals(traingle) # $x   $y
    args(traingle) # function (x, y) NULL
    # body和deparse查看函数方法体
    body(traingle) # sqrt(x^2 + y^2)
    deparse(traingle) # "function (x, y) "    "{"                   "    sqrt(x^2 + y^2)" "}" 
    # ...匹配
    # 假设有以下函数
    normalize <- function(x,m = mean(x),s = sd(x)){
      (x-m)/s
    }
    # 如果传入的参数中有空值
    normalize(c(1,3,5,10,NA)) # 将会得到NA结果:[1] NA NA NA NA NA
    # ... 解决了这个问题
    better_normalize <- function(x,m= mean(x,...),s=sd(x,...),...){
      (x-m)/s
    }
    better_normalize(c(1,3,5,10,NA)) # 依然输出[1] NA NA NA NA NA
    better_normalize(c(1,3,5,10,NA),na.rm=TRUE) # [1] -0.97094667 -0.45310844  0.06472978  1.35932533          NA
    # ...其实很精妙,上面例子中,传入的值匹配到最后一个..., 然后这个值会匹配到所有形参的...,
    # 而mean和sd本来就有na.rm=TRUE参数,所以翻译过来就是
    # better_normalize(c(1,3,5,10,NA),m= mean(x,na.rm=TRUE),s=sd(x,na.rm=TRUE),na.rm=TRUE)
    
    # do.call将函数作为参数传递
    # 注意:list里的每一项既是一个参数,其数量要和函数形参数量相等,否则报错
    # 由于better_normalizez还有一个参数,所以list只能包含一个数据
    do.call(better_normalize,list(c(1:100)))
    # 最常见的是do.call与rbind混用
    df1 = data.frame(x=1:5,y=rt(5,1))
    df2 = data.frame(x=6:10,y=rt(5,1,1))
    df3 = data.frame(x=11:15,y=rbeta(5,1,1))
    do.call(rbind,list(df1,df2,df3))
    # 匿名方式传递函数
    do.call(function(x,y)x+y,list(1:10,10:1)) #  [1]  11 11 11 11 11 11 11 11 11 11
    
    

    Chp7_字符串与因子

    #############################################################
    ##################### 字符串 ################################
    #############################################################
    
    # 如何从现有的字符串中构造出一个新的字符串; •
    # 如何格式化数字的打印格式; •
    # 了解特殊字符,如制表和换行符; •
    # 如何创建和操作因子
    rm(list = ls())
    
    # 在 R 中,“字符串”是个常用的非正式术语,因为正式的“字符向量元素”读起来相当拗口。
    # c()创建字符向量
    str = c("aaa","bbb")
    
    # paste 函数能将不同字符串组合在起来。在它传入的参数向量中,每个元素都能自我循环
    # 以达到最长的矢量长度,然后字符串就被拼接在一起,中间以空格分开。可以使用参数
    # sep 更改分隔符,或使用相关的 paste0 函数去掉分隔符。所有的字符串被组合后,可使用
    # collapse 参数把结果收缩成一个包含所有元素的字符串:
    paste(c("red","green"),"lorry") # "red lorry"   "green lorry"
    paste(c("red","green"),"lorry",sep = "-") # "red-lorry"   "green-lorry"
    paste(c("red","green"),"lorry",collapse =  ",") # "red lorry,green lorry"
    paste0(c("red","green"),"lorry") # "redlorry"   "greenlorry"
    
    # toString 函数是 paste 的变种,它在打印向量时非常有用。它使用逗号和空格分隔每个元
    # 素,且可限制打印的数量。在下例中, width = 40 将输出限制为 40 个字符:
    x<-(1:15) ^2
    toString(x) # [1] "1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225"
    toString(x,width = 30) # [1] "1, 4, 9, 16, 25, 36, 49, 6...."
    
    #noquote 函数去掉这些引号
    noquote(str) # aaa bbb
    
    ## 格式化数字
    
    # formatC函数使用C风格
    formatC(pi,digits = 40,format = "e",flag = "+") # "+3.1415926535897931159979634685441851615906e+00
    # C 风格的格式化函数 sprintf 
    pow <- 1:3
    powers_of_e <- exp(pow)
    sprintf("%s %d = %f", "Euler's constant to the power", pow, powers_of_e) # "Euler's constant to the power 1 = 2.718282"  "Euler's constant to the power 2 = 7.389056"  "Euler's constant to the power 3 = 20.085537" 
    
    # 特殊字符
    #  \t 制表符
    # \n 换行(注意不是\r\n)
    alarm()
    cat("\a")
    
    
    # tolower() toupper()
    
    # substring()和substr()截取字符串
    # 在大多数情况下,你可以随便选一个使用。不过,如果你传入了不同长度的向量参数,
    # 它们的行为会略有不同。对substring 来说,输出的长度与最长的输入一样;
    # 而对 substr 来说,输出的长度只与第一个输入的相等:
    woodchuck <- c(
      "How much wood would a woodchuck chuck",
      "If a woodchuck could chuck wood?",
      "He would chuck, he would, as much as he could",
      "And chuck as much wood as a woodchuck would",
      "If a woodchuck could chuck wood."
    )
    substring(woodchuck,1:6,3)
    substr(woodchuck,1:6,3)
    
    # strsplit分割字符串
    # 一定注意此方法返回的是一个list
    #  fixed = TRUE 意味着 split 的参数是固定长度的字符串而非正则表达式:
    strsplit(woodchuck," ",fixed = TRUE)
    # 正则匹配
    strsplit(woodchuck,",? ")
    
    # 文件路径
    # file.path()类似c#的path.combine
    file.path("c:","program files") # "c:/program files"
    # path.expand将相对路径转换为绝对路径
    path.expand("~") # "C:/Users/jnmcl/Documents"
    path.expand(".")
    # basename只返回文件名
    basename("C:/Program Files/R/R-devel/bin/x64/RGui.exe")
    
    
    
    #############################################################
    ##################### 因子 ##################################
    #############################################################
    
    # 当你用一列文本数据创建数据框时,R 将文本默认为类别数据并进行转换
    heights <- data.frame(
      height_cm = c(153, 181, 150, 172, 165, 149, 174, 169, 198, 163),
      gender = c(
        "female", "male", "female", "male", "male",
        "female", "female", "male", "male", "female"
      )
    )
    class(heights$gender) # "factor"
    # levels - 水平
    levels(heights$gender) # "female" "male"
    # nlevels - 水平的级数:相当于因子 level 的 length 
    nlevels(heights$gender) # 2
    # 也可以使用 factor 函数创建
    genders <- factor(c("female", "male", "female", "male", "male"))
    # 通过指定 levels 参数来更改因子被创建时水平的先后顺序
    genders <- factor(c("female", "male", "female", "male", "male"),levels=c("male","female"))
    # 不能使用 levels 函数直接改变因子的水平值。因为这将重新为每一个水平打
    # 上标签,更改数据值,这通常不是我们想要的。
    # 直接设置因子的水平值会将数据中的 male 变成 female,female 变成 male
    levels(genders) <- c("male", "female")
    # relevel 函数是另一种改变因子水平顺序的方法。在这种情况下,你只需指定第一个水平值
    relevel(genders, "male")
    #  droplevels 函数删除未使用的水平因子
    genders <- factor(c("female", "male", "female", "male", "male"),levels=c("male","female","unknown"))
    levels(genders)# "male"    "female"  "unknown"
    droplevels(genders) # Levels: male female
    
    ######有序因子######
    happy_choices <- c("depressed", "grumpy", "so-so", "cheery", "ecstatic")
    happy_values <- sample(
      happy_choices,
      10000,
      replace = TRUE)
    # 此时的5个因子在逻辑上其实是有序的,使用 ordered 函数
    # (或通过给 factor传入 order = TRUE 参数)可实现这个功能
    happy_ord <- ordered(happy_values, happy_choices)
    head(happy_ord) # depressed < grumpy < so-so < cheery < ecstatic : 顺序和因子定义时一致
    
    ####将连续变量转换为类别####
    # 例子:生成10000个服从beta分布的工人年龄数据
    ages = 16+50*rbeta(10000,2,3)
    # 按每十年分组
    age_groups = cut(ages,seq.int(16,66,10))
    head(age_groups)
    table(age_groups) #(16,26] (26,36] (36,46] (46,56] (56,66] 
                      # 1789    3475    2945    1524     267
    
    
    ####将类别变量转换为连续变量####
    
    #在清理脏数据时非常有用
    #在下例中,其中一个数字有两个小数点
    #遇到这样的情况,R会把这一列整体变成字符向量
    dirty <- data.frame(
      x = c("1.23", "4..56", "7.89")
    )
    
    # 要想把 x 列转换为数字,先把因子转换为字符向量,再转换为数值
    as.numeric(as.character(dirty$x)) # 1.23   NA 7.89
    # 更好的方法是将因子水平转换为数字,然后再像上面一样重建因子
    as.numeric(levels(dirty$x))[as.integer(dirty$x)]
    # 如果你经常使用它,就把它包装成一个函数以方便调用:
    factor_to_numeric <- function(f)
    {
      as.numeric(levels(f))[as.integer(f)]
    }
    
    
    # 为了平衡数据,使到在每个水平上的数据点的数目相等,可用 gl 函数来生成因子。它最
    # 简单的形式是:第一个整型参数为要生成的因子的水平数,第二个为每个水平需要重复的
    # 次数。通常你想为每个水平命名,这可以通过给 label 参数传入一个字符向量来实现。
    gl(3, 2, labels = c("placebo", "drug A", "drug B")) 
    #[1] placebo placebo drug A  drug A  drug B  drug B 
    #Levels: placebo drug A drug B
    # 还可以通过传入 length 参数以创建更复杂的水平排序,例如交替值(alternating value)
    gl(3, 1, 6, labels = c("placebo", "drug A", "drug B")) # 交替
    ## [1] placebo drug A drug B placebo drug A drug B
    ## Levels: placebo drug A drug B
    # 合并因子
    treatment <- gl(3, 2, labels = c("placebo", "drug A", "drug B"))
    gender <- gl(2, 1, 6, labels = c("female", "male"))
    interaction(treatment, gender)
    ## [1] placebo.female placebo.male drug A.female drug A.male
    ## [5] drug B.female drug B.male
    ## 6 Levels: placebo.female drug A.female drug B.female ... drug B.male
    
    

    chp9_高级循环

    rm(list = ls())
    
    #######replacation######
    #rep和replicate一样
    rep(runif(1), 5)
    replicate(5, runif(1))
    
    ####xpply家族###########33
    
    # lapply , 作用于list,返回作用后的新list
    list = list(one = 1,
                two = c(2, 2, 2),
                three = 1:10)
    lapply(list, unique)
    
    # lapply , 作用于list,返回vector,它一定需要第三个参数
    # 即返回值的模板
    vapply(list, length, numeric(1))
    
    # sapply, 介于lapply和vapply之间,
    # 其含义为:简化列表应用,它不需要模板,会尽可能的匹配
    # 但正因为如此,其返回值是不可预测的,可能是列表,也可能是向量
    sapply(list, length)
    sapply(list(), length) # 返回list()
    
    # 遍历文件夹下的所有R脚本并执行
    scripts = dir(pattern = "\\.R$")
    lapply(scripts, source)
    
    # 以上所有xapply函数都能作用于向量
    # 如果xapply的函数部分需要传额外的参数,紧跟逗号后传入即可
    # 注意:这只适用于向量参数(下面例子里的1:5)是第一个参数的情况
    lapply(1:5, rep.int, times = 3)
    # 如果向量参数不是第一个,就需要自定义函数封装
    lapply(1:5, function(x) {
      rep.int(4, times = x)
    })
    
    #eapply遍历环境列表
    env = new.env()
    env$ltes = letters
    eapply(env, length)
    
    # rapply是lapply的递归版本,但一般使用unlist扁平化列表后操作
    
    ######apply###########
    # 所有的xapply函数都是将传入的列表或向量(x)打散,按照列来逐一执行的
    # 如果想按行执行遍历操作,该怎么做呢?
    # 为举例说明,先用matlab包生成一个4×4方阵
    if (!require("matlab"))
      install.packages("matlab")
    library(matlab)
    magic4 = magic(4)
    # 可使用rowSums计算行的总数
    rowSums(magic4)
    # 如何统计每行数据?答案是使用apply函数
    # apply(a,b,c)
    # a: 一般是一个matrix,也可以是数据框,但比较少见,因为数据框各列数据类型可以不同
    # b: 应用于:1:应用于每一行2:每列,更大的数字表示更高的维度
    # c:函数
    apply(magic4, 2, summary)
    
    #当对数据框按照列应用apply函数,其作用与sapply一样
    # 因为sapply会自动决定返回类型,这种情况下它会返回数据框(数据框是非嵌套的列表)
    sapply(magic4, summary)
    
    a <- data.frame(1:14)
    b <- data.frame(15:30)
    mapply(summary, a, b)
    
    
    # split-apply-combine
    scores =  data.frame(player = rep(c("tom", "dick", "karry"), times = c(2, 5, 3)),
                         score = round(rlnorm(10, 8),-1))
    
    # split 将数据框拆分成3个元素的列表
    # split(x, f, drop = FALSE, ...)
    # x:vector or dataframe
    # f: x中的因子,上例中,player是因子
    # drop: if levels that do not occur should be dropped (if f is a factor or a list).
    scoreByPlayer = with(scores,
                         split(score, player))
    
    # apply
    scoreMean = lapply(scoreByPlayer, mean)
    
    # combine
    # 最后一步是把结果合并到单个向量中
    result = unlist(scoreMean)
    # dick    karry      tom
    # 4124.000 4126.667 2110.000
    
    ######tapply#######
    ###一次性执行上述三个步骤
    result = with(scores,
                  tapply(score,  player, mean))
    
    
    
    
    ################ plyr package ############################
    # plyr是一系列名为**ply的函数,其中的星号分别代表输入和输出的形式
    # 如:llply,list-list; 相同于lapply
    library(plyr)
    llply(scoreByPlayer, mean)
    # laply : list-vector(注意不是lapply)
    laply(scoreByPlayer, mean)
    #r开头的raply: 可以取代replicate
    raply(5, runif(1)) # 0.90486329 0.07345407 0.04568905 0.54464207 0.75477330
    # rlply返回列表
    rlply(5, runif(1))
    # rdply返回数据框
    df = rdply(5, runif(1))
    # ddply: 最常用,数据框-数据框,可以替换tapply
    # 下面是第一种用法:使用colwise,表示除了.()里面的列以外,对其余列都使用mean方法
    # ddply将对数据框自动分组
    dfx <- data.frame(
      group = c(rep('A', 8), rep('B', 15), rep('C', 6)),
      sex = sample(c("M", "F"), size = 29, replace = TRUE),
      age = runif(n = 29, min = 18, max = 54)
    )
    d1 = ddply(dfx, .(group,sex), colwise(mean))
    # group sex      age
    # 1     A   F 36.31042
    # 2     A   M 34.24761
    # 3     B   F 32.15730
    # 4     B   M 35.86387
    # 5     C   F 40.98684
    # 6     C   M 24.91566
    
    #第二种是使用summarize,这时必须手动指定每一列 
    d2 = ddply(dfx,.(group),summarize,age_mean = mean(age))
    # group age_mean
    # 1     A 35.27902
    # 2     B 33.88703
    # 3     C 35.62978
    

    相关文章

      网友评论

        本文标题:Learn R 笔记(PART1)

        本文链接:https://www.haomeiwen.com/subject/sivntctx.html