07高级数据管理

数学函数
abs(x) 绝对值
sqrt(x) 平方根
ceiling(x) 向上取整函数
floor(x) 向下取整函数
trunc(x) 向0截取
round(x) 四舍五入函数
signif(x) 截取有效位
cos(x),sin(x),tan(x)
acos(x),asin(x),atan(x)
cosh(x),sinh(x),tanh(x)
acosh(x),asinh(x),atanh(x)
log(x),log10(x)
exp(x) 指数函数
当这些函数被应用于数值向量、矩阵或数据框时,它们会作用于每一个独立的值。

统计函数
mean(x) 平均数
median(x) 中位数
sd(x) 标准差
var(x) 方差
mad(x) 绝对中位数
quantile(x) 分位数
range(x) 求值域
sum(x) 求和
min(x) 最小值
max(x) 最大值
scale(x) 对数据进行中心化或标准化

> x <- c(1, 2, 3, 4, 5, 6, 7, 8)
> mean(x)
[1] 4.5
> sd(x)
[1] 2.44949
> n <- length(x)
> meanx <- sum(x)/n
> css <- sum((x - meanx)^2)
> sdx <- sqrt(css/(n - 1))
> meanx
[1] 4.5
> sdx
[1] 2.44949

数据的标准化
默认情况下,函数scale()对矩阵或数据框的指定列进行均值为 0、标准差为 1 的标准化。
要对每一列进行任意均值和标准差的标准化:

newdata <- scale(mydata)*SD + M

其中的M是想要的均值,SD为想要的标准差。
要对指定列而不是整个矩阵或数据框进行标准化:

newdata <- transform(mydata, myvar = scale(myvar)*10+50)

将变量myvar标准化为均值 50、标准差为 10 的变量。

概率函数
概率函数通常用来生成特征已知的模拟数据,以及在用户编写的统计函数中计算概率值。
概率函数形如:

[dpqr]distribution_abbreviation()

d 密度函数
p 分布函数
q 分位数函数
r 生成随机数(随机偏差)

常用的概率函数:
beta Beta分布
binom 二项分布
cauchy 柯西分布
chisq (非中心)卡方分布
exp 指数分布
f F分布
gamma Gamma分布
geom 几何分布
hyper 超几何分布
lnorm 对数正态分布
logis Logistic分布
multinom 多项分布
nbinom 负二项分布
norm 正态分布
pois 泊松分布
signrank Wilcoxon符号秩分布
t t分布
unif 均匀分布
weibull Weibull分布
wilcox Wilcoxon秩和分布

> x <- pretty(c(-3, 3), 30)
> y <- dnorm(x)
> plot(x, y, type="l", xlab="Normal Deviate", ylab="Density", yaxs="i")
image.png
> pnorm(1.96)
[1] 0.9750021
> qnorm(.9, mean=500, sd=100)
[1] 628.1552
> rnorm(50, mean=50, sd=10)
 [1] 50.90701 23.30479 49.26953 43.69341 58.33219 74.55983 48.87788 50.07223
 [9] 51.13661 52.04896 49.29812 60.97722 68.27475 51.88737 49.31403 48.46568
[17] 47.35525 57.26836 54.03473 44.85644 61.34435 59.34282 71.21762 55.63532
[25] 49.81657 46.91496 38.88280 62.15051 40.71857 58.62943 49.45462 48.82537
[33] 38.55603 28.34087 64.75731 52.24712 48.94070 52.32623 61.49825 31.68802
[41] 45.84526 57.47583 52.81701 61.53104 51.57661 56.20224 47.86015 53.98346
[49] 54.56368 56.29681

设定随机种子
在每次生成伪随机数的时候,函数都会使用一个不同的种子,因此也会产生不同的结果。你可以通过函数set.seed()显式指定这个种子,让结果可以重现(reproducible)。

> runif(5)
[1] 0.9505711 0.1176140 0.7294812 0.8418611 0.8859856
> runif(5)
[1] 0.65070547 0.03970935 0.17168482 0.99797468 0.91804578
> set.seed(1234)
> runif(5)
[1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154
> set.seed(1234)
> runif(5)
[1] 0.1137034 0.6222994 0.6092747 0.6233794 0.8609154

生成多元正态数据
在模拟研究和蒙特卡洛方法中,经常需要获取来自给定均值向量和协方差阵的多元正态分布的数据。MASS包中的mvrnorm()函数可以让这个问题变得很容易。其调用格式为:

mvrnorm(n, mean, sigma)

n是想要的样本大小,mean为均值向量,sigma是方差-协方差矩阵(或相关矩阵)。

> library(MASS)

载入程辑包:‘MASS’

The following object is masked from ‘package:dplyr’:

    select

Warning message:
程辑包‘MASS’是用R版本3.6.3 来建造的 
> options(digits=3)
> set.seed(1234)
> mean <- c(230.7, 146.7, 3.6)
> sigma <- matrix(c(15360.8, 6721.2, -47.1, 6721.2, 4700.9, -16.5, -47.1, -16.5, 0.3), nrow=3, ncol=3)
> mydata <- mvrnorm(500, mean, sigma)
> mydata <- as.data.frame(mydata)
> names(mydata) <- c("y", "x1", "x2")
> dim(mydata)
[1] 500   3
> head(mydata, n=10)
       y    x1   x2
1   98.8  41.3 3.43
2  244.5 205.2 3.80
3  375.7 186.7 2.51
4  -59.2  11.2 4.71
5  313.0 111.0 3.45
6  288.8 185.1 2.72
7  134.8 165.0 4.39
8  171.7  97.4 3.64
9  167.2 101.0 3.50
10 121.1  94.5 4.10

R 中的概率函数允许生成模拟数据,这些数据是从服从已知特征的概率分布中抽样而得的。

字符处理函数
nchar(x) 计算字符数量
substr(x, stop, start) 提取或替换一个字符向量中的子串
grep(pattern, x, ignore, case=FALSE, fixed=FALSE) 搜索某种模式。若fixed=FALSE,则pattern为一个正则表达式。若fixed=TRUE,则pattern为一个文本字符串。返回值为匹配的下标。
sub(pattern, replacement, x, ignore.case=FALSE, fixed=FALSE) 在x中搜索pattern,并以文本replacement将其替换。若fixed=FALSE,则pattern为一个正则表达式。若fixed=TRUE,则pattern为一个文本字符串。
strsplit(x, split, fixed=FALSE) 在split处分割字符向量x中的元素。若fixed=FALSE,则pattern为一个正则表达式。若fixed=TRUE,则pattern为一个文本字符串。
paste(..., sep="") 连接字符串,分隔符为sep。
toupper(x) 大写转换
tolower(x) 小写转换

将函数应用于矩阵和数据框

> a <- 5
> sqrt(5)
[1] 2.24
> b <- c(1.243, 5.654, 2.99)
> round(b)
[1] 1 6 3
> c <- matrix(runif(12), nrow=3)
> c
       [,1]  [,2]  [,3]  [,4]
[1,] 0.9636 0.216 0.289 0.913
[2,] 0.2068 0.240 0.804 0.353
[3,] 0.0862 0.197 0.378 0.931
> log(c)
        [,1]  [,2]   [,3]    [,4]
[1,] -0.0371 -1.53 -1.241 -0.0912
[2,] -1.5762 -1.43 -0.218 -1.0402
[3,] -2.4511 -1.62 -0.972 -0.0710
> mean(c)
[1] 0.465
> mydata <- matrix(rnorm(30), nrow=6)
> mydata
       [,1]   [,2]   [,3]   [,4]   [,5]
[1,]  0.459  1.203  1.234  0.591 -0.281
[2,] -1.261  0.769 -1.891 -0.435  0.812
[3,] -0.527  0.238 -0.223 -0.251 -0.208
[4,] -0.557 -1.415  0.768 -0.926  1.451
[5,] -0.374  2.934  0.388  1.087  0.841
[6,] -0.604  0.935  0.609 -1.944 -0.866
> apply(mydata, 1, mean)
[1]  0.641 -0.401 -0.194 -0.136  0.975 -0.374
> apply(mydata, 2, mean)
[1] -0.478  0.777  0.148 -0.313  0.292
> apply(mydata, 2, mean, trim=0.2)
[1] -0.516  0.786  0.386 -0.255  0.291

本例中,截尾均值基于中间 60% 的数据,最高和最低 20% 的值均被忽略。

数据处理难题的一套解决方案

> options(digits=2)
> Student <- c("John Davis", "Angela Williams", "Bullwinkle Moose", "David Jones", "Janice Markhammer", "Cheryl Cushing", "Reuven Ytzrhak", "Greg Knox", "Joel England", "Mary Rayburn")
> Math <- c(502, 600, 412, 358, 495, 512, 410, 625, 573, 522)
> Science <- c(95, 99, 80, 82, 75, 85, 80, 95, 89, 86)
> English <- c(25, 22, 18, 15, 20, 28, 15, 30, 27, 18)
> roster <- data.frame(Student, Math, Science, English, stringsAsFactors=FALSE )
> roster
             Student Math Science English
1         John Davis  502      95      25
2    Angela Williams  600      99      22
3   Bullwinkle Moose  412      80      18
4        David Jones  358      82      15
5  Janice Markhammer  495      75      20
6     Cheryl Cushing  512      85      28
7     Reuven Ytzrhak  410      80      15
8          Greg Knox  625      95      30
9       Joel England  573      89      27
10      Mary Rayburn  522      86      18

由于数学、科学和英语考试的分值不同(均值和标准差相去甚远),在组合之前需要先让它们变得可以比较。一种方法是将变量进行标准化,这样每科考试的成绩就都是用单位标准差来表示,而不是以原始的尺度来表示了。

> z <- scale(roster[, 2:4])
> z
        Math Science English
 [1,]  0.013   1.078   0.587
 [2,]  1.143   1.591   0.037
 [3,] -1.026  -0.847  -0.697
 [4,] -1.649  -0.590  -1.247
 [5,] -0.068  -1.489  -0.330
 [6,]  0.128  -0.205   1.137
 [7,] -1.049  -0.847  -1.247
 [8,]  1.432   1.078   1.504
 [9,]  0.832   0.308   0.954
[10,]  0.243  -0.077  -0.697
attr(,"scaled:center")
   Math Science English 
    501      87      22 
attr(,"scaled:scale")
   Math Science English 
   86.7     7.8     5.5 
> score <- apply(z, 1, mean)
> roster <- cbind(roster, score)
> roster
             Student Math Science English score
1         John Davis  502      95      25  0.56
2    Angela Williams  600      99      22  0.92
3   Bullwinkle Moose  412      80      18 -0.86
4        David Jones  358      82      15 -1.16
5  Janice Markhammer  495      75      20 -0.63
6     Cheryl Cushing  512      85      28  0.35
7     Reuven Ytzrhak  410      80      15 -1.05
8          Greg Knox  625      95      30  1.34
9       Joel England  573      89      27  0.70
10      Mary Rayburn  522      86      18 -0.18
> y <- quantile(roster$score, c(.8, .6, .4, .2))
> y
  80%   60%   40%   20% 
 0.74  0.44 -0.36 -0.89 
> roster$grade[score>=y[1]] <- "A"
> roster$grade[score<y[1] & score>=y[2]] <- "B"
> roster$grade[score<y[2] & score>=y[3]] <- "C"
> roster$grade[score<y[3] & score>=y[4]] <- "D"
> roster$grade[score<y[4]] <- "F"
> roster
             Student Math Science English score grade
1         John Davis  502      95      25  0.56     B
2    Angela Williams  600      99      22  0.92     A
3   Bullwinkle Moose  412      80      18 -0.86     D
4        David Jones  358      82      15 -1.16     F
5  Janice Markhammer  495      75      20 -0.63     D
6     Cheryl Cushing  512      85      28  0.35     C
7     Reuven Ytzrhak  410      80      15 -1.05     F
8          Greg Knox  625      95      30  1.34     A
9       Joel England  573      89      27  0.70     B
10      Mary Rayburn  522      86      18 -0.18     C
> name <- strsplit((roster$Student), " ")
> name
[[1]]
[1] "John"  "Davis"

[[2]]
[1] "Angela"   "Williams"

[[3]]
[1] "Bullwinkle" "Moose"     

[[4]]
[1] "David" "Jones"

[[5]]
[1] "Janice"     "Markhammer"

[[6]]
[1] "Cheryl"  "Cushing"

[[7]]
[1] "Reuven"  "Ytzrhak"

[[8]]
[1] "Greg" "Knox"

[[9]]
[1] "Joel"    "England"

[[10]]
[1] "Mary"    "Rayburn"

> Firstname <- sapply(name, "[", 1)
> Lastname <- sapply(name, "[", 2)
> roster <- cbind(Firstname, Lastname, roster[, -1])
> roster
    Firstname   Lastname Math Science English score grade
1        John      Davis  502      95      25  0.56     B
2      Angela   Williams  600      99      22  0.92     A
3  Bullwinkle      Moose  412      80      18 -0.86     D
4       David      Jones  358      82      15 -1.16     F
5      Janice Markhammer  495      75      20 -0.63     D
6      Cheryl    Cushing  512      85      28  0.35     C
7      Reuven    Ytzrhak  410      80      15 -1.05     F
8        Greg       Knox  625      95      30  1.34     A
9        Joel    England  573      89      27  0.70     B
10       Mary    Rayburn  522      86      18 -0.18     C
> roster[order(Lastname, Firstname),]
    Firstname   Lastname Math Science English score grade
6      Cheryl    Cushing  512      85      28  0.35     C
1        John      Davis  502      95      25  0.56     B
9        Joel    England  573      89      27  0.70     B
4       David      Jones  358      82      15 -1.16     F
8        Greg       Knox  625      95      30  1.34     A
5      Janice Markhammer  495      75      20 -0.63     D
3  Bullwinkle      Moose  412      80      18 -0.86     D
10       Mary    Rayburn  522      86      18 -0.18     C
2      Angela   Williams  600      99      22  0.92     A
7      Reuven    Ytzrhak  410      80      15 -1.05     F

控制流

for结构语法:

for (var in seq) statement
> for (i in 1:10){
+   print("Hello")
+ }
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"

while结构语法:

while (cond) statement
> while (i > 0){
+   print("Hello")
+   i <- i - 1
+ }
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"
[1] "Hello"

if-else结构语法:

if (cond) statement
if (cond) statement1 else statement2
> if (is.character(roster$grade)) roster$grade <- as.factor(roster$grade)
> if (!is.factor(roster$grade)) roster$grade <- as.factor(roster$grade) else print("Grade already is a factor")
[1] "Grade already is a factor"

ifelse语法结构:

ifelse(cond, statement1, statement2)
> ifelse(score>0.5, print("Passed"), print("Failed"))
[1] "Passed"
[1] "Failed"
 [1] "Passed" "Passed" "Failed" "Failed" "Failed" "Failed" "Failed" "Passed" "Passed" "Failed"
> outcome <- ifelse(score > 0.5, "Passed", "Failed")
> outcome
 [1] "Passed" "Passed" "Failed" "Failed" "Failed" "Failed" "Failed" "Passed" "Passed" "Failed"

switch结构语法:

switch(expr, ...)
> feelings <- c("sad", "afraid")
> for (i in feelings){
+   print(switch(i,
+                happy = "I am glad you are happy",
+                afraid = "There is nothing to fear",
+                sad = "Cheer up",
+                angry = "Calm down now"))
+ }
[1] "Cheer up"
[1] "There is nothing to fear"

用户自编函数

函数语法:

myfunction <- function(arg1, arg2, ... ){
  statements
  return(object)
}

函数中的对象只在函数内部使用,返回对象的数据类型是任意的,从标量到列表皆可。
编写一个函数,用来计算数据对象的集中趋势和散布情况,此函数可以选择性地给出参数统计量(均值和标准差)和非参数统计量(中位数和绝对中位差),结果以一个含名称列表的形式给出,另外可以选择是否自动输出结果。除非另外指定,否则此函数的默认行为是计算参数统计量并且不输出结果。

> mystats <- function(x, parametric=TRUE, print=FALSE){
+   if (parametric){
+     center <- mean(x)
+     spread <- sd(x)
+   } else {
+     center <- median(x)
+     spread <- mad(x)
+   }
+   if (print & parametric){
+     cat("Mean=", center, "\n", "SD=", spread, "\n")
+   } else if (print & !parametric){
+     cat("Median=", center, "\n", "MAD=", spread, "\n")
+   }
+   result <- list(center=center, spread=spread)
+   return(result)
+ }
> set.seed(1234)
> x <- rnorm(500)
> y <- mystats(x)
> y$center
[1] 0.0018
> y$spread
[1] 1
> y <- mystats(x, parametric=FALSE, print=TRUE)
Median= -0.021 
 MAD= 1 

让用户选择输出当天日期的格式,在函数声明中为参数指定的值将作为其默认值,在函数mydate()中,如果未指定type,则long将为默认的日期格式。

> mydate <- function(type="long"){
+   switch(type,
+          long = format(Sys.time(), "%A %B %d %Y"),
+          short = format(Sys.time(), "%m-%d-%y"),
+          cat(type, "is not a recognized type\n")
+          )
+ }
> mydate("long")
[1] "星期日 十月 11 2020"
> mydate("short")
[1] "10-11-20"
> mydate()
[1] "星期日 十月 11 2020"
> mydate("medium")
medium is not a recognized type

cat()仅会在输入的日期格式类型不匹配"long"或"short"时执行。
有若干函数可以用来为函数添加错误捕获和纠正功能,可以使用函数warning()来生成一条错误提示信息,用message()来生成一条诊断信息,或用stop()停止当前表达式的执行并提示错误。

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