27 数据读取技巧

27.1 日期数据

设文件dates.csv中包含如下内容,并设其文件编码为GBK:

序号,出生日期,发病日期
1,1941/3/8,2007/1/1
2,1972/1/24,2007/1/1
3,1932/6/1,2007/1/1
4,1947/5/17,2007/1/1
5,1943/3/10,2007/1/1
6,1940/1/8,2007/1/1
7,1947/8/5,2007/1/1
8,2005/4/14,2007/1/1
9,1961/6/23,2007/1/2
10,1949/1/10,2007/1/2

先把日期当作字符串读入:

## Parsed with column specification:
## cols(
##   序号 = col_double(),
##   出生日期 = col_character(),
##   发病日期 = col_character()
## )

然后用lubridate::ymd()函数转换为R日期类型:

也可以用R本身的as.POSIXct函数转换:

经过转换后的数据为:

序号 出生日期 发病日期 出生日期ct 发病日期ct
1 1941/3/8 2007/1/1 1941-03-08 2007-01-01
2 1972/1/24 2007/1/1 1972-01-24 2007-01-01
3 1932/6/1 2007/1/1 1932-06-01 2007-01-01
4 1947/5/17 2007/1/1 1947-05-17 2007-01-01
5 1943/3/10 2007/1/1 1943-03-10 2007-01-01
6 1940/1/8 2007/1/1 1940-01-08 2007-01-01
7 1947/8/5 2007/1/1 1947-08-05 2007-01-01
8 2005/4/14 2007/1/1 2005-04-14 2007-01-01
9 1961/6/23 2007/1/2 1961-06-23 2007-01-02
10 1949/1/10 2007/1/2 1949-01-10 2007-01-02

以上读入日期是比较保险的做法。 还可以直接在read_csv()函数中指定某列为col_date()

## # A tibble: 10 x 3
##     序号 出生日期   发病日期  
##    <int> <date>     <date>    
##  1     1 1941-03-08 2007-01-01
##  2     2 1972-01-24 2007-01-01
##  3     3 1932-06-01 2007-01-01
##  4     4 1947-05-17 2007-01-01
##  5     5 1943-03-10 2007-01-01
##  6     6 1940-01-08 2007-01-01
##  7     7 1947-08-05 2007-01-01
##  8     8 2005-04-14 2007-01-01
##  9     9 1961-06-23 2007-01-02
## 10    10 1949-01-10 2007-01-02

27.1.1 日期差计算

R的日期可以用difftime计算差值。 为了计算发病时的年龄,包括小数部分,可以这样计算:

序号 出生日期 发病日期 发病年龄(带小数年)
1 1941-03-08 2007-01-01 65.82
2 1972-01-24 2007-01-01 34.94
3 1932-06-01 2007-01-01 74.58
4 1947-05-17 2007-01-01 59.63
5 1943-03-10 2007-01-01 63.81
6 1940-01-08 2007-01-01 66.98
7 1947-08-05 2007-01-01 59.41
8 2005-04-14 2007-01-01 1.72
9 1961-06-23 2007-01-02 45.53
10 1949-01-10 2007-01-02 57.98

27.1.2 计算周岁

如果按照大家通常计算周岁的方法计算年龄, 算法就不仅包括年的差, 还要判断是否到了本年的生日。

用lubridate包的功能计算周岁如下:

用R本身的功能实现周岁计算如下:

d.dates()计算发病时周岁年龄:

序号 出生日期 发病日期 发病年龄(带小数年) 发病年龄
1 1941-03-08 2007-01-01 65.82 65
2 1972-01-24 2007-01-01 34.94 34
3 1932-06-01 2007-01-01 74.58 74
4 1947-05-17 2007-01-01 59.63 59
5 1943-03-10 2007-01-01 63.81 63
6 1940-01-08 2007-01-01 66.98 66
7 1947-08-05 2007-01-01 59.41 59
8 2005-04-14 2007-01-01 1.72 1
9 1961-06-23 2007-01-02 45.53 45
10 1949-01-10 2007-01-02 57.98 57

27.2 缺失值处理

设有如下的bp.csv数据,以GBK编码保存:

序号,收缩压
1,145
5,110
6,未测
9,150
10,拒绝
15,115

其中的血压有非数值内容。 直接用read.csv读入:

## Parsed with column specification:
## cols(
##   序号 = col_double(),
##   收缩压 = col_character()
## )
## # A tibble: 6 x 2
##    序号 收缩压
##   <dbl> <chr> 
## 1     1 145   
## 2     5 110   
## 3     6 未测  
## 4     9 150   
## 5    10 拒绝  
## 6    15 115

读入的收缩压被当成了字符型列,无法进行计算。

把字符型的收缩压转换为数值型:

## Warning: 强制改变过程中产生了NA
序号 收缩压 收缩压数值
1 145 145
5 110 110
6 未测 NA
9 150 150
10 拒绝 NA
15 115 115

收缩压中非数值的项被转换为数值型缺失值, 并在转换时有警告信息。 注意这里同时保存了原始输入的收缩压和转换为数值的收缩压, 这样便于数据核对。

27.3 练习

  • 读入patients.csv, 把其中的日期转换为R日期类型, 计算发病年龄。保存为tibble数据框d.patients。

  • 读入cancer.csv, 保存为d.cancer。 v0是放疗前肿瘤体积, v1是放疗后肿瘤体积。 计算放疗后肿瘤缩减率。