tidy.md 6.0 KB

数据整理

科学实验原始数据格式多种多样,这给数据处理分析带来困难。如果有一个统一的数据格式,可以降低数据的复杂性,便于理解和交流,也给统计程序开发者提供方便,增加数据逻辑的使用范围。庆幸的是,科学数据都可以转化为字段和记录两向列表的形式。这个两向表遵循以下三条规则:

  • 列代表变量(或字段),每个变量一列
  • 行代表观测(或记录),每个观测值一行
  • 每个单元格代表该变量在该观测中的观测值 这是日常生活和科研记录中的常用记录数据形式,但为了节省纸张、或者为了数据紧凑直观,有时候也不这样记录,特别是对于多因素试验的情况。比如,这个表: 为了数据分析的需要,需要先将这种形式的数据转化为上述标准格式。这个过程叫做数据整理(tidy),整理好的标准数据也叫做tidy数据。
tidyverse、tidyr

tidyverse是用于数据整理的R包。 安装:install.packages('tidyverse') 或者安装其轻量版本 install.packages("tidyr") 如想使用最新版本,可以从源码安装: install.packages("devtools") devtools::install_github("tidyverse/tidyr")

使用: library('tidyr')

筛选记录(filter)

filter(flights, month == 1, day == 1) 比较运算符:>, >=, <, <=, != (不等于), and == (等于). 注意,等于是==而不是=,前者是比较运算符,后者是赋值运算符,这一点容易出错。

另外需要注意的是在使用==比较浮点数时,计算机提供的有限精度的近似而不是绝对精确的数值(物质的有限可分性原理)

sqrt(2) ^ 2 其实并不等于2,测试一下:

sqrt(2) ^ 2
#> [1] FALSE
1/49 * 49 == 1
#> [1] FALSE

这时不要使用==,代之以near()函数:

near(sqrt(2) ^ 2,  2)
#> [1] TRUE
near(1 / 49 * 49, 1)
#> [1] TRUE

逻辑运算符:|、& 、!、xor filter(flights, month == 11 | month == 12)

排序(arrange)

arrange(flights, year, month, desc(day))

选择列(select)

  • 按列名选择: select(flights, year, month, day)
  • 选择两个列之间的所有列,包括自身,[year:day]
    select(flights, year:day)
  • 排除选择:
    select(flights, -(year:day))
  • 选择开头 starts_with("abc")//匹配列名以“abc”开头的列。
  • 选择结尾: ends_with("xyz"): //匹配列名以“xyz”结尾的列.
  • 包含: contains("ijk") //匹配列名包含"ijk"的列
  • 匹配正则表达式 matches("(.)\1"): 匹配列名有重复字符的列。
  • 匹配数字范围
    num_range("x", 1:3) //匹配列名为x1,x2,x3

重命名列(rename)

rename(flights, tail_num = tailnum)

变异(mutate)

mutate(突变,变异),如病毒变异、DNA突变。 mutate从现有变量产生新的变量,并加到现有变量的后面。

flights_sml <- select(flights, 
  year:day, 
  ends_with("delay"), 
  distance, 
  air_time
)
mutate(flights_sml,
  gain = arr_delay - dep_delay,
  speed = distance / air_time * 60
)

如果只需要新的变量,而不包括原有变量,使用transmute

transmute(flights,
  gain = arr_delay - dep_delay,
  hours = air_time / 60,
  gain_per_hour = gain / hours
)

运算符:%/% 整除, %% 求余, +, -, *, /, sum(), log(), log2(), log10(() , lead(), tag()

分组汇总(summarize)

summarise(flights, delay = mean(dep_delay, na.rm = TRUE))

summarize()与group_by()配合使用。

by_day <- group_by(flights, year, month, day)
summarise(by_day, delay = mean(dep_delay, na.rm = TRUE))

使用管道(%>%)

对于一系列的操作,组成一个操作序列的情况,前一个操作的结果作为后一个操作的参数。这时可以通过管道来组织代码,使得整个流程更加清晰,代码的可读性也会提高。数据作为参数在函数中流动,与物体在管道中的流动模型十分相似,因此这种组合的处理方式叫做管道,管道符号为%>%,前一个函数的输出结果,作为后一个函数的第一个参数输入并且书写是省略参数名,而默认为第一个参数。如,x %>% f(y) 变成 f(x, y), 而x %>% f(y) %>% g(z) 变成 g(f(x, y), z)。

delays <- flights %>% 
  group_by(dest) %>% 
  summarise(
    count = n(),
    dist = mean(distance, na.rm = TRUE),
    delay = mean(arr_delay, na.rm = TRUE)
  ) %>% 
  filter(count > 20, dest != "HNL")

这样处理流程更清晰,代码更整洁了。

有用的汇总函数

位置量度 mean()、median()

平均值和中位数

not_cancelled %>% 
  group_by(year, month, day) %>% 
  summarise(
    avg_delay1 = mean(arr_delay),
    avg_delay2 = mean(arr_delay[arr_delay > 0]) # the average positive delay
  )
分散量度 sd()、IQR()、mad()
not_cancelled %>% 
  group_by(dest) %>% 
  summarise(distance_sd = sd(distance)) %>% 
  arrange(desc(distance_sd))
Measures of rank: min(x), quantile(x, 0.25), max()
not_cancelled %>% 
  group_by(year, month, day) %>% 
  summarise(
    first = min(dep_time),
    last = max(dep_time)
  )
Measures of position: first(x), nth(x, 2), last(x)
not_cancelled %>% 
  group_by(year, month, day) %>% 
  summarise(
    first_dep = first(dep_time), 
    last_dep = last(dep_time)
  )
计数 n()

n()函数返回当前组的大小,即当前组包含的记录数。 sum(!is.na(x))返回非空记录数,n_distinct(x)返回非重复记录数。

not_cancelled %>% 
  group_by(dest) %>% 
  summarise(carriers = n_distinct(carrier)) %>% 
  arrange(desc(carriers))

计数

not_cancelled %>% 
  count(dest)

加权计数:

not_cancelled %>% 
  count(tailnum, wt = distance)
计数和比例

sum(x > 10), 当x为数值型,TRUE转化为1,FALSE转化为0,然后计算总和,这实际上是对满足该条件的记录数。mean(y == 0)则返回满足该条件的记录占总记录数的比例。

多变量分组

daily <- group_by(flights, year, month, day)